1 /*
   2  * Copyright (c) 2014, 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 8032808
  27  * @run main/othervm -Xcheck:jni Test
  28  * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
  29  * @run main/othervm/policy=policy.success -Xcheck:jni Test success
  30  */
  31 
  32 import java.net.*;
  33 import java.io.IOException;
  34 import java.nio.channels.*;
  35 import java.util.concurrent.*;
  36 import java.util.Set;
  37 import jdk.net.*;
  38 
  39 public class Test {
  40 
  41     static boolean security;
  42     static boolean success;
  43     static int testCount = 0;
  44 
  45     interface Runner {
  46         public void run() throws Exception;
  47     }
  48 
  49     static void test(String msg) {
  50         testCount++;
  51         System.out.println("***************************************");
  52         System.out.println("Test " + testCount + ": " + msg);
  53     }
  54 
  55     static void passed() {
  56         System.out.println("Test passed.");
  57     }
  58 
  59     static void failed() {
  60         System.out.println("Test failed.");
  61     }
  62 
  63     static void check(boolean pass) {
  64         if (pass) {
  65             passed();
  66         } else {
  67             failed();
  68         }
  69     }
  70 
  71     public static void main(String[] args) throws Exception {
  72 
  73         // quick check to see if supportedOptions() working before
  74         // creating any sockets and libnet loaded
  75 
  76         Sockets.supportedOptions(Socket.class);
  77 
  78         security = System.getSecurityManager() != null;
  79         success = security && args[0].equals("success");
  80 
  81         // Main thing is to check for JNI problems
  82         // Doesn't matter if current system does not support the option
  83         // and currently setting the option with the loopback interface
  84         // doesn't work either
  85 
  86         System.out.println ("Security Manager enabled: " + security);
  87         if (security) {
  88             System.out.println ("Success expected: " + success);
  89         }
  90 
  91         final SocketFlow flowIn = SocketFlow.create()
  92             .bandwidth(1000)
  93             .priority(SocketFlow.HIGH_PRIORITY);
  94 
  95         boolean flowsupported = true;
  96         boolean reuseportsupported = true;
  97 
  98         // If option not available, end test
  99         DatagramSocket dg = new DatagramSocket(0);
 100         Set<SocketOption<?>> options = dg.supportedOptions();
 101         if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
 102             System.out.println("SO_FLOW_SLA not supported");
 103             flowsupported = false;
 104         }
 105         if (!options.contains(ExtendedSocketOptions.SO_REUSEPORT)) {
 106             System.out.println("SO_REUSEPORT not supported");
 107             reuseportsupported = false;
 108         }
 109 
 110         if (flowsupported) {
 111             ServerSocket ss = new ServerSocket(0);
 112             int tcp_port = ss.getLocalPort();
 113             final InetAddress loop = InetAddress.getByName("127.0.0.1");
 114             final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
 115 
 116             final int udp_port = dg.getLocalPort();
 117 
 118             final Socket s = new Socket("127.0.0.1", tcp_port);
 119             final SocketChannel sc = SocketChannel.open();
 120             sc.connect (new InetSocketAddress("127.0.0.1", tcp_port));
 121 
 122             doTest(()->{
 123                 Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 124             });
 125             doTest(()->{
 126                 Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
 127             });
 128             doTest(()->{
 129                 sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 130             });
 131             doTest(()->{
 132                 sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA);
 133             });
 134             doTest(()->{
 135                 DatagramSocket dg1 = new DatagramSocket(0);
 136                 dg1.connect(loop, udp_port);
 137                 Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 138             });
 139             doTest(()->{
 140                 DatagramChannel dg2 = DatagramChannel.open();
 141                 dg2.bind(new InetSocketAddress(loop, 0));
 142                 dg2.connect(new InetSocketAddress(loop, udp_port));
 143                 dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 144             });
 145             doTest(()->{
 146                 MulticastSocket mc1 = new MulticastSocket(0);
 147                 mc1.connect(loop, udp_port);
 148                 Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 149             });
 150             doTest(()->{
 151                 AsynchronousSocketChannel asc = AsynchronousSocketChannel.open();
 152                 Future<Void> f = asc.connect(loopad);
 153                 f.get();
 154                 asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
 155             });
 156         }
 157         if (reuseportsupported) {
 158             Socket s1 = new Socket();
 159             Socket s2 = new Socket();
 160             test("Socket should be created with SO_REUSEPORT disabled");
 161             check(!Sockets.getOption(s1, ExtendedSocketOptions.SO_REUSEPORT));
 162 
 163             test("Socket.set ReusePort(true)");
 164             Sockets.setOption(s1, ExtendedSocketOptions.SO_REUSEPORT, true);
 165             check(Sockets.getOption(s1, ExtendedSocketOptions.SO_REUSEPORT));
 166 
 167             test("Socket.set ReusePort(false)");
 168             Sockets.setOption(s1, ExtendedSocketOptions.SO_REUSEPORT, false);
 169             check(!Sockets.getOption(s1, ExtendedSocketOptions.SO_REUSEPORT));
 170 
 171             test("Without setting SO_REUSEPORT, binding Socket to port already in use should throw a SocketException");
 172             s1.bind(new InetSocketAddress(0));
 173             try {
 174                 s2.bind( new InetSocketAddress(s1.getLocalPort()));
 175                 failed();
 176             } catch (SocketException e) {
 177                 passed();
 178             }
 179             s1.close();
 180             s2.close();
 181 
 182             test("By setting SO_REUSEPORT, binding Socket to port already in use should not throw a SocketException");
 183             s1 = new Socket();
 184             s2 = new Socket();
 185             Sockets.setOption(s1, ExtendedSocketOptions.SO_REUSEPORT, true);
 186             Sockets.setOption(s2, ExtendedSocketOptions.SO_REUSEPORT, true);
 187             s1.bind(new InetSocketAddress(0));
 188             try {
 189                 s2.bind( new InetSocketAddress(s1.getLocalPort()) );
 190                 passed();
 191             } catch (SocketException e) {
 192                 failed();
 193             }
 194             s1.close();
 195             s2.close();
 196 
 197             ServerSocket ss1 = new ServerSocket();
 198             ServerSocket ss2 = new ServerSocket();
 199 
 200             test("Server Socket should be created with SO_REUSEPORT disabled");
 201             check(!Sockets.getOption(ss1, ExtendedSocketOptions.SO_REUSEPORT));
 202                 
 203             test("ServerSocket set ReusePort(true)");
 204             Sockets.setOption(ss1, ExtendedSocketOptions.SO_REUSEPORT, true);
 205             check(Sockets.getOption(ss1, ExtendedSocketOptions.SO_REUSEPORT));
 206                 
 207             test("ServerSocket set ReusePort(false)");
 208             Sockets.setOption(ss1, ExtendedSocketOptions.SO_REUSEPORT, false);
 209             check(!Sockets.getOption(ss1, ExtendedSocketOptions.SO_REUSEPORT));
 210             
 211             test("Without setting SO_REUSEPORT, binding Server Socket to port already in use should throw a SocketException");
 212             ss1.bind(new InetSocketAddress(0));
 213             try {
 214                 ss2.bind( new InetSocketAddress(ss1.getLocalPort()));
 215                 failed();
 216             } catch (SocketException e) {
 217                     passed();
 218             }
 219             ss1.close();
 220             ss2.close();
 221                 
 222             test("By setting SO_REUSEPORT, binding Server Socket to port already in use should not throw a SocketException");
 223             ss1 = new ServerSocket();
 224             ss2 = new ServerSocket();
 225             Sockets.setOption(ss1, ExtendedSocketOptions.SO_REUSEPORT, true);
 226             Sockets.setOption(ss2, ExtendedSocketOptions.SO_REUSEPORT, true);
 227             ss1.bind(new InetSocketAddress(0));
 228             try {
 229                 ss2.bind( new InetSocketAddress(ss1.getLocalPort()) );
 230                 passed();
 231             } catch (SocketException e) {
 232                 failed();
 233             }
 234             ss1.close();
 235             ss2.close();
 236 
 237             DatagramSocket dg1 = new DatagramSocket(null);
 238             DatagramSocket dg2 = new DatagramSocket(null);
 239 
 240             test("DatagramSocket should be created with SO_REUSEPORT disabled");
 241             check(!Sockets.getOption(dg1, ExtendedSocketOptions.SO_REUSEPORT));
 242                 
 243             test("DatagramSocket.setReusePort(true)");
 244             Sockets.setOption(dg1, ExtendedSocketOptions.SO_REUSEPORT, true);
 245             check(Sockets.getOption(dg1, ExtendedSocketOptions.SO_REUSEPORT));
 246                 
 247             test("DatagramSocket.setReusePort(false)");
 248             Sockets.setOption(dg1, ExtendedSocketOptions.SO_REUSEPORT, false);
 249             check(!Sockets.getOption(dg1, ExtendedSocketOptions.SO_REUSEPORT));
 250                 
 251             test("Without setting SO_REUSEPORT, binding Server Socket to port already in use should throw a SocketException");
 252             dg1.bind(new InetSocketAddress(0));
 253             try {
 254                 dg2.bind( new InetSocketAddress(dg1.getLocalPort()));
 255                 failed();
 256             } catch (SocketException e) {
 257                 passed();
 258             }
 259             dg1.close();
 260             dg2.close();
 261                 
 262             test("By setting SO_REUSEPORT, binding Server Socket to port already in use should not throw a SocketException");
 263             dg1 = new DatagramSocket(null);
 264             dg2 = new DatagramSocket(null);
 265             Sockets.setOption(dg1, ExtendedSocketOptions.SO_REUSEPORT, true);
 266             Sockets.setOption(dg2, ExtendedSocketOptions.SO_REUSEPORT, true);
 267             dg1.bind(new InetSocketAddress(0));
 268             try {
 269                 dg2.bind( new InetSocketAddress(dg1.getLocalPort()) );
 270                 passed();
 271             } catch (SocketException e) {
 272                 failed();
 273             }
 274             dg1.close();
 275             dg2.close();
 276 
 277             MulticastSocket mc1 = new MulticastSocket();
 278             
 279             test("Check SO_REUSEPORT is enabled in MulticastSocket");
 280             check(Sockets.getOption(mc1, ExtendedSocketOptions.SO_REUSEPORT));
 281             mc1.close();
 282 
 283             test("Check SO_REUSEPORT is not disabled by MulticastSocket.bind()");
 284             mc1 = new MulticastSocket(null);
 285 
 286             InetSocketAddress isa = new InetSocketAddress(
 287                                     InetAddress.getLocalHost(), 0);
 288             mc1.bind(isa);
 289             check(Sockets.getOption(mc1, ExtendedSocketOptions.SO_REUSEPORT));
 290             mc1.close();
 291        }
 292     }
 293 
 294     static void doTest(Runner func) throws Exception {
 295         try {
 296             func.run();
 297             if (security && !success) {
 298                 throw new RuntimeException("Test failed");
 299             }
 300         } catch (SecurityException e) {
 301             if (success) {
 302                 throw new RuntimeException("Test failed");
 303             }
 304         } catch (UnsupportedOperationException e) {
 305             System.out.println (e);
 306         } catch (IOException e) {
 307             // Probably a permission error, but we're not
 308             // going to check unless a specific permission exception
 309             // is defined.
 310             System.out.println (e);
 311         }
 312     }
 313 }