test/jdk/java/net/SocketImpl/SocketImplCombinations.java
changeset 54155 b5a73f22b2bd
child 57268 adcdd45830a0
child 58423 54de0c861d32
equal deleted inserted replaced
54154:1caf2daef7cf 54155:b5a73f22b2bd
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 8220493
       
    27  * @modules java.base/java.net:+open java.base/sun.nio.ch:+open
       
    28  * @run testng/othervm SocketImplCombinations
       
    29  * @summary Test Socket and ServerSocket with combinations of SocketImpls
       
    30  */
       
    31 
       
    32 import java.io.FileDescriptor;
       
    33 import java.io.IOException;
       
    34 import java.io.InputStream;
       
    35 import java.io.OutputStream;
       
    36 import java.lang.reflect.Field;
       
    37 import java.net.InetAddress;
       
    38 import java.net.InetSocketAddress;
       
    39 import java.net.Proxy;
       
    40 import java.net.ServerSocket;
       
    41 import java.net.Socket;
       
    42 import java.net.SocketAddress;
       
    43 import java.net.SocketImpl;
       
    44 import java.net.SocketImplFactory;
       
    45 import java.nio.channels.ServerSocketChannel;
       
    46 import java.nio.channels.SocketChannel;
       
    47 import java.util.function.BiConsumer;
       
    48 
       
    49 import org.testng.annotations.Test;
       
    50 import static org.testng.Assert.*;
       
    51 
       
    52 @Test
       
    53 public class SocketImplCombinations {
       
    54 
       
    55     /**
       
    56      * Test creating an unconnected Socket, it should be created with a platform SocketImpl.
       
    57      */
       
    58     public void testNewSocket1() throws IOException {
       
    59         try (Socket s = new Socket()) {
       
    60             SocketImpl si = getSocketImpl(s);
       
    61             assertTrue(isSocksSocketImpl(si));
       
    62             SocketImpl delegate = getDelegate(si);
       
    63             assertTrue(isPlatformSocketImpl(delegate));
       
    64         }
       
    65     }
       
    66 
       
    67     /**
       
    68      * Test creating a connected Socket, it should be created with a platform SocketImpl.
       
    69      */
       
    70     public void testNewSocket2() throws IOException {
       
    71         try (ServerSocket ss = new ServerSocket(0)) {
       
    72             try (Socket s = new Socket(ss.getInetAddress(), ss.getLocalPort())) {
       
    73                 SocketImpl si = getSocketImpl(s);
       
    74                 assertTrue(isSocksSocketImpl(si));
       
    75                 SocketImpl delegate = getDelegate(si);
       
    76                 assertTrue(isPlatformSocketImpl(delegate));
       
    77             }
       
    78         }
       
    79     }
       
    80 
       
    81     /**
       
    82      * Test creating a Socket for a DIRECT connection, it should be created with a
       
    83      * platform SocketImpl.
       
    84      */
       
    85     public void testNewSocket3() throws IOException {
       
    86         try (Socket s = new Socket(Proxy.NO_PROXY)) {
       
    87             SocketImpl si = getSocketImpl(s);
       
    88             assertTrue(isPlatformSocketImpl(si));
       
    89         }
       
    90     }
       
    91 
       
    92     /**
       
    93      * Test creating a Socket for a SOCKS connection, it should be created with a
       
    94      * SOCKS SocketImpl.
       
    95      */
       
    96     public void testNewSocket4() throws IOException {
       
    97         var address = new InetSocketAddress("127.0.0.1", 1080);
       
    98         var socksProxy = new Proxy(Proxy.Type.SOCKS, address);
       
    99         try (Socket s = new Socket(socksProxy)) {
       
   100             SocketImpl si = getSocketImpl(s);
       
   101             assertTrue(isSocksSocketImpl(si));
       
   102             SocketImpl delegate = getDelegate(si);
       
   103             assertTrue(isPlatformSocketImpl(delegate));
       
   104         }
       
   105     }
       
   106 
       
   107     /**
       
   108      * Test creating a Socket for a HTTP proxy connection, it should be created with
       
   109      * a HTTP proxy SocketImpl.
       
   110      */
       
   111     public void testNewSocket5() throws IOException {
       
   112         var address = new InetSocketAddress("127.0.0.1", 8080);
       
   113         var httpProxy = new Proxy(Proxy.Type.HTTP, address);
       
   114         try (Socket s = new Socket(httpProxy)) {
       
   115             SocketImpl si = getSocketImpl(s);
       
   116             assertTrue(isHttpConnectSocketImpl(si));
       
   117             SocketImpl delegate = getDelegate(si);
       
   118             assertTrue(isPlatformSocketImpl(delegate));
       
   119         }
       
   120     }
       
   121 
       
   122     /**
       
   123      * Test creating a Socket no SocketImpl. A platform SocketImpl should be
       
   124      * created lazily.
       
   125      */
       
   126     public void testNewSocket6() throws IOException {
       
   127         Socket s = new Socket((SocketImpl) null) { };
       
   128         try (s) {
       
   129             assertTrue(getSocketImpl(s) == null);
       
   130             s.bind(new InetSocketAddress(0));   // force SocketImpl to be created
       
   131             SocketImpl si = getSocketImpl(s);
       
   132             assertTrue(isSocksSocketImpl(si));
       
   133             SocketImpl delegate = getDelegate(si);
       
   134             assertTrue(isPlatformSocketImpl(delegate));
       
   135         }
       
   136     }
       
   137 
       
   138     /**
       
   139      * Test creating a Socket with a custom SocketImpl.
       
   140      */
       
   141     public void testNewSocket7() throws IOException {
       
   142         Socket s = new Socket(new CustomSocketImpl(false)) { };
       
   143         try (s) {
       
   144             SocketImpl si = getSocketImpl(s);
       
   145             assertTrue(si instanceof CustomSocketImpl);
       
   146         }
       
   147     }
       
   148 
       
   149     /**
       
   150      * Test creating a Socket when there is a SocketImplFactory set.
       
   151      */
       
   152     public void testNewSocket8() throws IOException {
       
   153         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   154         try (Socket s = new Socket()) {
       
   155             SocketImpl si = getSocketImpl(s);
       
   156             assertTrue(si instanceof CustomSocketImpl);
       
   157         } finally {
       
   158             setSocketSocketImplFactory(null);
       
   159         }
       
   160     }
       
   161 
       
   162     /**
       
   163      * Test creating a Socket for a DIRECT connection when there is a
       
   164      * SocketImplFactory set.
       
   165      */
       
   166     public void testNewSocket9() throws IOException {
       
   167         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   168         try (Socket s = new Socket(Proxy.NO_PROXY)) {
       
   169             SocketImpl si = getSocketImpl(s);
       
   170             assertTrue(si instanceof CustomSocketImpl);
       
   171         } finally {
       
   172             setSocketSocketImplFactory(null);
       
   173         }
       
   174     }
       
   175 
       
   176     /**
       
   177      * Test creating a Socket for a SOCKS connection when there is a
       
   178      * SocketImplFactory set.
       
   179      */
       
   180     public void testNewSocket10() throws IOException {
       
   181         var address = new InetSocketAddress("127.0.0.1", 1080);
       
   182         var socksProxy = new Proxy(Proxy.Type.SOCKS, address);
       
   183         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   184         try (Socket s = new Socket(socksProxy)) {
       
   185             SocketImpl si = getSocketImpl(s);
       
   186             assertTrue(isSocksSocketImpl(si));
       
   187             SocketImpl delegate = getDelegate(si);
       
   188             assertTrue(isPlatformSocketImpl(delegate));
       
   189         } finally {
       
   190             setSocketSocketImplFactory(null);
       
   191         }
       
   192     }
       
   193 
       
   194     /**
       
   195      * Test creating a Socket for a HTTP proxy connection when there is a
       
   196      * SocketImplFactory set.
       
   197      */
       
   198     public void testNewSocket11() throws IOException {
       
   199         var address = new InetSocketAddress("127.0.0.1", 8080);
       
   200         var httpProxy = new Proxy(Proxy.Type.HTTP, address);
       
   201         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   202         try (Socket s = new Socket(httpProxy)) {
       
   203             SocketImpl si = getSocketImpl(s);
       
   204             assertTrue(isHttpConnectSocketImpl(si));
       
   205             SocketImpl delegate = getDelegate(si);
       
   206             assertTrue(isPlatformSocketImpl(delegate));
       
   207         } finally {
       
   208             setSocketSocketImplFactory(null);
       
   209         }
       
   210     }
       
   211 
       
   212     /**
       
   213      * Test creating a Socket no SocketImpl when there is a SocketImplFactory set.
       
   214      */
       
   215     public void testNewSocket12() throws IOException {
       
   216         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   217         try {
       
   218             Socket s = new Socket((SocketImpl) null) { };
       
   219             try (s) {
       
   220                 assertTrue(getSocketImpl(s) == null);
       
   221                 s.bind(new InetSocketAddress(0));   // force SocketImpl to be created
       
   222                 assertTrue(getSocketImpl(s) instanceof CustomSocketImpl);
       
   223             }
       
   224         } finally {
       
   225             setSocketSocketImplFactory(null);
       
   226         }
       
   227     }
       
   228 
       
   229     /**
       
   230      * Test creating an unbound ServerSocket, it should be created with a platform
       
   231      * SocketImpl.
       
   232      */
       
   233     public void testNewServerSocket1() throws IOException {
       
   234         try (ServerSocket ss = new ServerSocket()) {
       
   235             SocketImpl si = getSocketImpl(ss);
       
   236             assertTrue(isPlatformSocketImpl(si));
       
   237         }
       
   238     }
       
   239 
       
   240     /**
       
   241      * Test creating a bound ServerSocket, it should be created with a platform
       
   242      * SocketImpl.
       
   243      */
       
   244     public void testNewServerSocket2() throws IOException {
       
   245         try (ServerSocket ss = new ServerSocket(0)) {
       
   246             SocketImpl si = getSocketImpl(ss);
       
   247             assertTrue(isPlatformSocketImpl(si));
       
   248         }
       
   249     }
       
   250 
       
   251     /**
       
   252      * Test creating a ServerSocket with a custom SocketImpl.
       
   253      */
       
   254     public void testNewServerSocket3() throws IOException {
       
   255         ServerSocket ss = new ServerSocket(new CustomSocketImpl(true)) { };
       
   256         try (ss) {
       
   257             SocketImpl si = getSocketImpl(ss);
       
   258             assertTrue(si instanceof CustomSocketImpl);
       
   259         }
       
   260     }
       
   261 
       
   262     /**
       
   263      * Test creating an unbound ServerSocket when there is a SocketImplFactory set.
       
   264      */
       
   265     public void testNewServerSocket4() throws IOException {
       
   266         setServerSocketImplFactory(() -> new CustomSocketImpl(true));
       
   267         try (ServerSocket ss = new ServerSocket()) {
       
   268             SocketImpl si = getSocketImpl(ss);
       
   269             assertTrue(si instanceof CustomSocketImpl);
       
   270         } finally {
       
   271             setServerSocketImplFactory(null);
       
   272         }
       
   273     }
       
   274 
       
   275     /**
       
   276      * Test creating a bound ServerSocket when there is a SocketImplFactory set.
       
   277      */
       
   278     public void testNewServerSocket5() throws IOException {
       
   279         setServerSocketImplFactory(() -> new CustomSocketImpl(true));
       
   280         try (ServerSocket ss = new ServerSocket(0)) {
       
   281             SocketImpl si = getSocketImpl(ss);
       
   282             assertTrue(si instanceof CustomSocketImpl);
       
   283         } finally {
       
   284             setServerSocketImplFactory(null);
       
   285         }
       
   286     }
       
   287 
       
   288     /**
       
   289      * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
       
   290      * the Socket to accept is created with no SocketImpl.
       
   291      */
       
   292     public void testServerSocketAccept1() throws IOException {
       
   293         var socket = new Socket((SocketImpl) null) { };
       
   294         assertTrue(getSocketImpl(socket) == null);
       
   295 
       
   296         serverSocketAccept(socket, (ss, s) -> {
       
   297             assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
       
   298             assertTrue(s == socket);
       
   299             SocketImpl si = getSocketImpl(s);
       
   300             assertTrue(isPlatformSocketImpl(si));
       
   301             checkFields(si);
       
   302         });
       
   303     }
       
   304 
       
   305     /**
       
   306      * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
       
   307      * the Socket to accept is created with no SocketImpl, and there is a custom
       
   308      * client SocketImplFactory set.
       
   309      */
       
   310     public void testServerSocketAccept2() throws IOException {
       
   311         var socket = new Socket((SocketImpl) null) { };
       
   312         assertTrue(getSocketImpl(socket) == null);
       
   313 
       
   314         serverSocketAccept(socket, () -> new CustomSocketImpl(false), (ss, s) -> {
       
   315             assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
       
   316             assertTrue(s == socket);
       
   317             SocketImpl si = getSocketImpl(s);
       
   318             assertTrue(isPlatformSocketImpl(si));
       
   319             checkFields(si);
       
   320         });
       
   321     }
       
   322 
       
   323     /**
       
   324      * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
       
   325      * the Socket to accept is created with a SocketImpl that delegates to a
       
   326      * platform SocketImpl.
       
   327      */
       
   328     public void testServerSocketAccept3() throws IOException {
       
   329         var socket = new Socket();
       
   330         SocketImpl si = getSocketImpl(socket);
       
   331         assertTrue(isSocksSocketImpl(si));
       
   332         SocketImpl delegate = getDelegate(si);
       
   333         assertTrue(isPlatformSocketImpl(delegate));
       
   334 
       
   335         serverSocketAccept(socket, (ss, s) -> {
       
   336             assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
       
   337             assertTrue(s == socket);
       
   338             SocketImpl psi = getSocketImpl(socket);
       
   339             assertTrue(isPlatformSocketImpl(psi));
       
   340             checkFields(psi);
       
   341         });
       
   342     }
       
   343 
       
   344     /**
       
   345      * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
       
   346      * the Socket to accept is created with a custom SocketImpl.
       
   347      */
       
   348     public void testServerSocketAccept4a() throws IOException {
       
   349         SocketImpl clientImpl = new CustomSocketImpl(false);
       
   350         Socket socket = new Socket(clientImpl) { };
       
   351         assertTrue(getSocketImpl(socket) == clientImpl);
       
   352 
       
   353         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   354             expectThrows(IOException.class, ss::accept);
       
   355         } finally {
       
   356             socket.close();
       
   357         }
       
   358     }
       
   359 
       
   360     public void testServerSocketAccept4b() throws IOException {
       
   361         SocketImpl clientImpl = new CustomSocketImpl(false);
       
   362         Socket socket = new Socket(clientImpl) { };
       
   363         assertTrue(getSocketImpl(socket) == clientImpl);
       
   364 
       
   365         setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
       
   366         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   367             expectThrows(IOException.class, ss::accept);
       
   368         } finally {
       
   369             setSocketSocketImplFactory(null);
       
   370             socket.close();
       
   371         }
       
   372     }
       
   373 
       
   374     /**
       
   375      * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
       
   376      * the Socket to accept is created no SocketImpl.
       
   377      */
       
   378     public void testServerSocketAccept5a() throws IOException {
       
   379         SocketImpl serverImpl = new CustomSocketImpl(true);
       
   380         try (ServerSocket ss = new ServerSocket(serverImpl) { }) {
       
   381             ss.bind(new InetSocketAddress(0));
       
   382             expectThrows(IOException.class, ss::accept);
       
   383         }
       
   384     }
       
   385 
       
   386     public void testServerSocketAccept5b() throws IOException {
       
   387         var socket = new Socket((SocketImpl) null) { };
       
   388         assertTrue(getSocketImpl(socket) == null);
       
   389 
       
   390         SocketImpl serverImpl = new CustomSocketImpl(true);
       
   391         try (ServerSocket ss = serverSocketToAccept(serverImpl, socket)) {
       
   392             expectThrows(IOException.class, ss::accept);
       
   393         } finally {
       
   394             socket.close();
       
   395         }
       
   396     }
       
   397 
       
   398     public void testServerSocketAccept5c() throws IOException {
       
   399         setServerSocketImplFactory(() -> new CustomSocketImpl(true));
       
   400         try (ServerSocket ss = new ServerSocket(0)) {
       
   401             expectThrows(IOException.class, ss::accept);
       
   402         } finally {
       
   403             setServerSocketImplFactory(null);
       
   404         }
       
   405     }
       
   406 
       
   407     public void testServerSocketAccept5d() throws IOException {
       
   408         var socket = new Socket((SocketImpl) null) { };
       
   409         assertTrue(getSocketImpl(socket) == null);
       
   410 
       
   411         setServerSocketImplFactory(() -> new CustomSocketImpl(true));
       
   412         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   413             expectThrows(IOException.class, ss::accept);
       
   414         } finally {
       
   415             setServerSocketImplFactory(null);
       
   416             socket.close();
       
   417         }
       
   418     }
       
   419 
       
   420     /**
       
   421      * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
       
   422      * the Socket to accept is created with no SocketImpl, and there is a custom
       
   423      * client SocketImplFactory set.
       
   424      */
       
   425     public void testServerSocketAccept6() throws Exception {
       
   426         var socket = new Socket((SocketImpl) null) { };
       
   427         assertTrue(getSocketImpl(socket) == null);
       
   428 
       
   429         SocketImpl serverImpl = new CustomSocketImpl(true);
       
   430         SocketImplFactory clientFactory = () -> new CustomSocketImpl(false);
       
   431         serverSocketAccept(serverImpl, socket, clientFactory, (ss, s) -> {
       
   432             assertTrue(getSocketImpl(ss) == serverImpl);
       
   433             SocketImpl si = getSocketImpl(s);
       
   434             assertTrue(si instanceof CustomSocketImpl);
       
   435             checkFields(si);
       
   436         });
       
   437     }
       
   438 
       
   439     /**
       
   440      * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
       
   441      * the Socket to accept is created with a SocketImpl that delegates to a
       
   442      * platform SocketImpl.
       
   443      */
       
   444     public void testServerSocketAccept7a() throws IOException {
       
   445         var socket = new Socket();
       
   446         SocketImpl si = getSocketImpl(socket);
       
   447         assertTrue(isSocksSocketImpl(si));
       
   448         SocketImpl delegate = getDelegate(si);
       
   449         assertTrue(isPlatformSocketImpl(delegate));
       
   450 
       
   451         SocketImpl serverImpl = new CustomSocketImpl(true);
       
   452         try (ServerSocket ss = serverSocketToAccept(serverImpl, socket)) {
       
   453             expectThrows(IOException.class, ss::accept);
       
   454         } finally {
       
   455             socket.close();
       
   456         }
       
   457     }
       
   458 
       
   459     public void testServerSocketAccept7b() throws IOException {
       
   460         var socket = new Socket();
       
   461         SocketImpl si = getSocketImpl(socket);
       
   462         assertTrue(isSocksSocketImpl(si));
       
   463         SocketImpl delegate = getDelegate(si);
       
   464         assertTrue(isPlatformSocketImpl(delegate));
       
   465 
       
   466         setServerSocketImplFactory(() -> new CustomSocketImpl(true));
       
   467         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   468             expectThrows(IOException.class, ss::accept);
       
   469         } finally {
       
   470             setServerSocketImplFactory(null);
       
   471             socket.close();
       
   472         }
       
   473     }
       
   474 
       
   475     /**
       
   476      * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
       
   477      * the Socket to accept is created with a custom SocketImpl.
       
   478      */
       
   479     public void testServerSocketAccept8() throws Exception {
       
   480         SocketImpl clientImpl = new CustomSocketImpl(false);
       
   481         Socket socket = new Socket(clientImpl) { };
       
   482         assertTrue(getSocketImpl(socket) == clientImpl);
       
   483 
       
   484         SocketImpl serverImpl = new CustomSocketImpl(true);
       
   485         SocketImplFactory clientFactory = () -> new CustomSocketImpl(false);
       
   486         serverSocketAccept(serverImpl, socket, clientFactory, (ss, s) -> {
       
   487             assertTrue(getSocketImpl(ss) == serverImpl);
       
   488             assertTrue(getSocketImpl(s) == clientImpl);
       
   489             checkFields(clientImpl);
       
   490         });
       
   491     }
       
   492 
       
   493     /**
       
   494      * Creates a ServerSocket that returns the given Socket from accept.
       
   495      * The consumer is invoked with the server socket and the accepted socket.
       
   496      */
       
   497     static void serverSocketAccept(Socket socket,
       
   498                                    BiConsumer<ServerSocket, Socket> consumer)
       
   499         throws IOException
       
   500     {
       
   501         Socket s1 = null;
       
   502         Socket s2 = null;
       
   503         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   504             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   505             s2 = ss.accept();
       
   506             consumer.accept(ss, s2);
       
   507         } finally {
       
   508             if (s1 != null) s1.close();
       
   509             if (s2 != null) s2.close();
       
   510         }
       
   511     }
       
   512 
       
   513     /**
       
   514      * Creates a ServerSocket that returns the given Socket from accept. The
       
   515      * given SocketImplFactory is set during the accept and the consumer is
       
   516      * invoked when the server socket and the accepted socket.
       
   517      */
       
   518     static void serverSocketAccept(Socket socket,
       
   519                                    SocketImplFactory factory,
       
   520                                    BiConsumer<ServerSocket, Socket> consumer)
       
   521         throws IOException
       
   522     {
       
   523         Socket s1 = null;
       
   524         Socket s2 = null;
       
   525         try (ServerSocket ss = serverSocketToAccept(socket)) {
       
   526             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   527             setSocketSocketImplFactory(factory);
       
   528             try {
       
   529                 s2 = ss.accept();
       
   530             } finally {
       
   531                 setSocketSocketImplFactory(null);
       
   532             }
       
   533             consumer.accept(ss, s2);
       
   534         } finally {
       
   535             if (s1 != null) s1.close();
       
   536             if (s2 != null) s2.close();
       
   537         }
       
   538     }
       
   539 
       
   540     /**
       
   541      * Creates a ServerSocket with a SocketImpl returns the given Socket from
       
   542      * accept. The given SocketImplFactory is set during the accept and the
       
   543      * consumer is invoked when the server socket and the accepted socket.
       
   544      */
       
   545     static void serverSocketAccept(SocketImpl impl,
       
   546                                    Socket socket,
       
   547                                    SocketImplFactory factory,
       
   548                                    BiConsumer<ServerSocket, Socket> consumer)
       
   549         throws IOException
       
   550     {
       
   551         Socket s1 = null;
       
   552         Socket s2 = null;
       
   553         try (ServerSocket ss = serverSocketToAccept(impl, socket)) {
       
   554             s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
       
   555             setSocketSocketImplFactory(factory);
       
   556             try {
       
   557                 s2 = ss.accept();
       
   558             } finally {
       
   559                 setSocketSocketImplFactory(null);
       
   560             }
       
   561             consumer.accept(ss, s2);
       
   562         } finally {
       
   563             if (s1 != null) s1.close();
       
   564             if (s2 != null) s2.close();
       
   565         }
       
   566     }
       
   567 
       
   568     /**
       
   569      * Creates a ServerSocket that returns the given Socket from accept.
       
   570      */
       
   571     static ServerSocket serverSocketToAccept(Socket s) throws IOException {
       
   572         return new ServerSocket(0) {
       
   573             @Override
       
   574             public Socket accept() throws IOException {
       
   575                 implAccept(s);
       
   576                 return s;
       
   577             }
       
   578         };
       
   579     }
       
   580 
       
   581     /**
       
   582      * Creates a ServerSocket with a SocketImpl that returns the given Socket
       
   583      * from accept.
       
   584      */
       
   585     static ServerSocket serverSocketToAccept(SocketImpl impl, Socket s) throws IOException {
       
   586         ServerSocket ss = new ServerSocket(impl) {
       
   587             @Override
       
   588             public Socket accept() throws IOException {
       
   589                 implAccept(s);
       
   590                 return s;
       
   591             }
       
   592         };
       
   593         ss.bind(new InetSocketAddress(0));
       
   594         return ss;
       
   595     }
       
   596 
       
   597     /**
       
   598      * Returns the socket's SocketImpl
       
   599      */
       
   600     static SocketImpl getSocketImpl(Socket s) {
       
   601         try {
       
   602             Field f = Socket.class.getDeclaredField("impl");
       
   603             f.setAccessible(true);
       
   604             return (SocketImpl) f.get(s);
       
   605         } catch (Exception e) {
       
   606             throw new RuntimeException(e);
       
   607         }
       
   608     }
       
   609 
       
   610     /**
       
   611      * Returns the server socket's SocketImpl
       
   612      */
       
   613     static SocketImpl getSocketImpl(ServerSocket ss) {
       
   614         try {
       
   615             Field f = ServerSocket.class.getDeclaredField("impl");
       
   616             f.setAccessible(true);
       
   617             return (SocketImpl) f.get(ss);
       
   618         } catch (Exception e) {
       
   619             throw new RuntimeException(e);
       
   620         }
       
   621     }
       
   622 
       
   623     /**
       
   624      * Returns the SocketImpl that the given SocketImpl delegates to
       
   625      */
       
   626     static SocketImpl getDelegate(SocketImpl si) {
       
   627         try {
       
   628             Class<?> clazz = Class.forName("java.net.DelegatingSocketImpl");
       
   629             Field f = clazz.getDeclaredField("delegate");
       
   630             f.setAccessible(true);
       
   631             return (SocketImpl) f.get(si);
       
   632         } catch (Exception e) {
       
   633             throw new RuntimeException(e);
       
   634         }
       
   635     }
       
   636 
       
   637     /**
       
   638      * Returns the value of a SocketImpl field
       
   639      */
       
   640     static <T> T get(SocketImpl si, String name) {
       
   641         try {
       
   642             Field f = SocketImpl.class.getDeclaredField(name);
       
   643             f.setAccessible(true);
       
   644             return (T) f.get(si);
       
   645         } catch (Exception e) {
       
   646             throw new RuntimeException(e);
       
   647         }
       
   648     }
       
   649 
       
   650     /**
       
   651      * Sets the value of SocketImpl field
       
   652      */
       
   653     static void set(SocketImpl si, String name, Object value) {
       
   654         try {
       
   655             Field f = SocketImpl.class.getDeclaredField(name);
       
   656             f.setAccessible(true);
       
   657             f.set(si, value);
       
   658         } catch (Exception e) {
       
   659             throw new RuntimeException(e);
       
   660         }
       
   661     }
       
   662 
       
   663     /**
       
   664      * Returns true if the SocketImpl is a PlatformSocketImpl
       
   665      */
       
   666     static boolean isPlatformSocketImpl(SocketImpl si) {
       
   667         try {
       
   668             Class<?> clazz = Class.forName("sun.net.PlatformSocketImpl");
       
   669             return clazz.isInstance(si);
       
   670         } catch (Exception e) {
       
   671             throw new RuntimeException(e);
       
   672         }
       
   673     }
       
   674 
       
   675     /**
       
   676      * Returns true if the SocketImpl is a SocksSocketImpl
       
   677      */
       
   678     static boolean isSocksSocketImpl(SocketImpl si) {
       
   679         try {
       
   680             Class<?> clazz = Class.forName("java.net.SocksSocketImpl");
       
   681             return clazz.isInstance(si);
       
   682         } catch (Exception e) {
       
   683             throw new RuntimeException(e);
       
   684         }
       
   685     }
       
   686 
       
   687     /**
       
   688      * Returns true if the SocketImpl is a HttpConnectSocketImpl
       
   689      */
       
   690     static boolean isHttpConnectSocketImpl(SocketImpl si) {
       
   691         try {
       
   692             Class<?> clazz = Class.forName("java.net.HttpConnectSocketImpl");
       
   693             return clazz.isInstance(si);
       
   694         } catch (Exception e) {
       
   695             throw new RuntimeException(e);
       
   696         }
       
   697     }
       
   698 
       
   699     /**
       
   700      * Socket.setSocketImplFactory(SocketImplFactory)
       
   701      */
       
   702     static void setSocketSocketImplFactory(SocketImplFactory factory) {
       
   703         try {
       
   704             Field f = Socket.class.getDeclaredField("factory");
       
   705             f.setAccessible(true);
       
   706             f.set(null, factory);
       
   707         } catch (Exception e) {
       
   708             throw new RuntimeException(e);
       
   709         }
       
   710     }
       
   711 
       
   712     /**
       
   713      * ServerSocket.setSocketFactory(SocketImplFactory)
       
   714      */
       
   715     static void setServerSocketImplFactory(SocketImplFactory factory) {
       
   716         try {
       
   717             Field f = ServerSocket.class.getDeclaredField("factory");
       
   718             f.setAccessible(true);
       
   719             f.set(null, factory);
       
   720         } catch (Exception e) {
       
   721             throw new RuntimeException(e);
       
   722         }
       
   723     }
       
   724 
       
   725     /**
       
   726      * Checks the 4 protected fields of a SocketImpl to make sure that they
       
   727      * have been initialized.
       
   728      */
       
   729     static void checkFields(SocketImpl si) {
       
   730         FileDescriptor fd = get(si, "fd");
       
   731         InetAddress address = get(si, "address");
       
   732         int port = get(si, "port");
       
   733         int localport = get(si, "localport");
       
   734         assertTrue(fd.valid() && address != null && port != 0 && localport != 0);
       
   735     }
       
   736 
       
   737     /**
       
   738      * Custom SocketImpl that is layed on a SocketChannel or ServerSocketChannel
       
   739      */
       
   740     static class CustomSocketImpl extends SocketImpl {
       
   741         private final boolean server;
       
   742         private ServerSocketChannel ssc;
       
   743         private SocketChannel sc;
       
   744 
       
   745         CustomSocketImpl(boolean server) {
       
   746             this.server = server;
       
   747         }
       
   748 
       
   749         @Override
       
   750         protected void create(boolean stream) throws IOException {
       
   751             if (server) {
       
   752                 ssc = ServerSocketChannel.open();
       
   753             } else {
       
   754                 sc = SocketChannel.open();
       
   755             }
       
   756         }
       
   757 
       
   758         @Override
       
   759         protected void connect(String host, int port) throws IOException {
       
   760             connect(new InetSocketAddress(host, port), 0);
       
   761         }
       
   762 
       
   763         @Override
       
   764         protected void connect(InetAddress address, int port) throws IOException {
       
   765             connect(new InetSocketAddress(address, port), 0);
       
   766         }
       
   767 
       
   768         @Override
       
   769         protected void connect(SocketAddress remote, int timeout) throws IOException {
       
   770             sc.connect(remote);
       
   771             super.address = ((InetSocketAddress) remote).getAddress();
       
   772             super.port = ((InetSocketAddress) remote).getPort();
       
   773         }
       
   774 
       
   775         @Override
       
   776         protected void bind(InetAddress address, int port) throws IOException {
       
   777             if (server) {
       
   778                 ssc.bind(new InetSocketAddress(address, port));
       
   779                 super.localport = ssc.socket().getLocalPort();
       
   780             } else {
       
   781                 sc.bind(new InetSocketAddress(address, port));
       
   782                 super.localport = sc.socket().getLocalPort();
       
   783             }
       
   784             super.address = address;
       
   785         }
       
   786 
       
   787         @Override
       
   788         protected void listen(int backlog) {
       
   789             // do nothing
       
   790         }
       
   791 
       
   792         @Override
       
   793         protected void accept(SocketImpl si) throws IOException {
       
   794             SocketChannel peer = ssc.accept();
       
   795             FileDescriptor fd;
       
   796             try {
       
   797                 Class<?> clazz = Class.forName("sun.nio.ch.SocketChannelImpl");
       
   798                 Field f = clazz.getDeclaredField("fd");
       
   799                 f.setAccessible(true);
       
   800                 fd = (FileDescriptor) f.get(peer);
       
   801             } catch (Exception e) {
       
   802                 throw new RuntimeException(e);
       
   803             }
       
   804             set(si, "fd", fd);
       
   805             set(si, "address", peer.socket().getInetAddress());
       
   806             set(si, "port", peer.socket().getPort());
       
   807             set(si, "localport", peer.socket().getLocalPort());
       
   808         }
       
   809 
       
   810         @Override
       
   811         protected InputStream getInputStream() {
       
   812             throw new RuntimeException();
       
   813         }
       
   814 
       
   815         @Override
       
   816         protected OutputStream getOutputStream() {
       
   817             throw new RuntimeException();
       
   818         }
       
   819 
       
   820         @Override
       
   821         protected int available() {
       
   822             return 0;
       
   823         }
       
   824 
       
   825         @Override
       
   826         protected void close() {
       
   827         }
       
   828 
       
   829         @Override
       
   830         protected void sendUrgentData(int data) {
       
   831             throw new RuntimeException();
       
   832         }
       
   833 
       
   834         @Override
       
   835         public void setOption(int option, Object value) {
       
   836             throw new RuntimeException();
       
   837         }
       
   838 
       
   839         @Override
       
   840         public Object getOption(int option) {
       
   841             throw new RuntimeException();
       
   842         }
       
   843     }
       
   844 }