1 /*
   2  * Copyright (c) 2014, 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 8032808 8044773
  27  * @modules jdk.net
  28  * @library /test/lib
  29  * @build jdk.test.lib.OSVersion jdk.test.lib.Platform
  30  * @run main/othervm -Xcheck:jni Test success
  31  * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
  32  * @run main/othervm/policy=policy.success -Xcheck:jni Test success
  33  */
  34 
  35 import jdk.net.SocketFlow;
  36 import jdk.net.Sockets;
  37 import jdk.test.lib.Platform;
  38 import jdk.test.lib.OSVersion;
  39 
  40 import java.io.IOException;
  41 import java.net.*;
  42 import java.nio.channels.AsynchronousSocketChannel;
  43 import java.nio.channels.DatagramChannel;
  44 import java.nio.channels.SocketChannel;
  45 import java.util.concurrent.Future;
  46 
  47 import static java.lang.System.out;
  48 import static jdk.net.ExtendedSocketOptions.SO_FLOW_SLA;
  49 
  50 public class Test {
  51 
  52     interface Runner { void run() throws Exception; }
  53 
  54     static boolean expectSuccess;
  55     private static final boolean expectSupport = checkExpectedOptionSupport();
  56 
  57     public static void main(String[] args) throws Exception {
  58 
  59         // quick check to see if supportedOptions() working before
  60         // creating any sockets and libnet loaded
  61 
  62         Sockets.supportedOptions(Socket.class);
  63 
  64         expectSuccess = args[0].equals("success");
  65 
  66         // Main thing is to check for JNI problems
  67         // Doesn't matter if currently setting the option with the loopback
  68         // interface doesn't work
  69 
  70         boolean sm = System.getSecurityManager() != null;
  71         out.println("Security Manager enabled: " + sm);
  72         out.println("Success expected: " + expectSuccess);
  73 
  74         SocketFlow flowIn = SocketFlow.create()
  75                                       .bandwidth(1000)
  76                                       .priority(SocketFlow.HIGH_PRIORITY);
  77 
  78         try (ServerSocket ss = new ServerSocket(0);
  79              DatagramSocket dg = new DatagramSocket(0)) {
  80 
  81             int tcp_port = ss.getLocalPort();
  82             final InetAddress loop = InetAddress.getLoopbackAddress();
  83             final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
  84 
  85             final int udp_port = dg.getLocalPort();
  86 
  87             final Socket s = new Socket(loop, tcp_port);
  88             final SocketChannel sc = SocketChannel.open();
  89             sc.connect(new InetSocketAddress(loop, tcp_port));
  90 
  91             doTest("Sockets.setOption Socket", () -> {
  92                 out.println(flowIn);
  93                 if (s.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
  94                     throw new RuntimeException("Unexpected supportedOptions()");
  95                 }
  96                 Sockets.setOption(s, SO_FLOW_SLA, flowIn);
  97                 out.println(flowIn);
  98             });
  99 
 100             doTest("Sockets.getOption Socket", () -> {
 101                 Sockets.getOption(s, SO_FLOW_SLA);
 102                 out.println(flowIn);
 103             });
 104 
 105             doTest("Sockets.setOption SocketChannel", () -> {
 106                 if (sc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 107                     throw new RuntimeException("Unexpected supportedOptions()");
 108                 }
 109                 sc.setOption(SO_FLOW_SLA, flowIn);
 110             });
 111             doTest("Sockets.getOption SocketChannel", () ->
 112                     sc.getOption(SO_FLOW_SLA)
 113             );
 114             doTest("Sockets.setOption DatagramSocket", () -> {
 115                 try (DatagramSocket dg1 = new DatagramSocket(0)) {
 116                     if (dg1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 117                         throw new RuntimeException("Unexpected supportedOptions()");
 118                     }
 119 
 120                     dg1.connect(loop, udp_port);
 121                     Sockets.setOption(dg1, SO_FLOW_SLA, flowIn);
 122                 }
 123             });
 124             doTest("Sockets.setOption DatagramSocket 2", () -> {
 125                 try (DatagramChannel dg2 = DatagramChannel.open()) {
 126                     if (dg2.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 127                         throw new RuntimeException("Unexpected supportedOptions()");
 128                     }
 129                     dg2.bind(new InetSocketAddress(loop, 0));
 130                     dg2.connect(new InetSocketAddress(loop, udp_port));
 131                     dg2.setOption(SO_FLOW_SLA, flowIn);
 132                 }
 133             });
 134             doTest("Sockets.setOption MulticastSocket", () -> {
 135                 try (MulticastSocket mc1 = new MulticastSocket(0)) {
 136                     if (mc1.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 137                         throw new RuntimeException("Unexpected supportedOptions()");
 138                     }
 139                     mc1.connect(loop, udp_port);
 140                     Sockets.setOption(mc1, SO_FLOW_SLA, flowIn);
 141                 }
 142             });
 143             doTest("Sockets.setOption AsynchronousSocketChannel", () -> {
 144                 try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
 145                     if (asc.supportedOptions().contains(SO_FLOW_SLA) != expectSupport) {
 146                         throw new RuntimeException("Unexpected supportedOptions()");
 147                     }
 148                     Future<Void> f = asc.connect(loopad);
 149                     f.get();
 150                     asc.setOption(SO_FLOW_SLA, flowIn);
 151                 }
 152             });
 153         }
 154     }
 155 
 156     static void doTest(String message, Runner func) throws Exception {
 157         out.println(message);
 158         try {
 159             func.run();
 160             if (expectSuccess) {
 161                 out.println("Completed as expected");
 162             } else {
 163                 throw new RuntimeException("Operation succeeded, but expected SecurityException");
 164             }
 165         } catch (SecurityException e) {
 166             if (expectSuccess) {
 167                 throw new RuntimeException("Unexpected SecurityException", e);
 168             } else {
 169                 out.println("Caught expected: " + e);
 170                 return;
 171             }
 172         } catch (UnsupportedOperationException e) {
 173             if (expectSupport) {
 174                 throw new RuntimeException("Test failed: " +
 175                         "unexpected UnsupportedOperationException");
 176             }
 177             out.println("UnsupportedOperationException as expected");
 178             return;
 179         } catch (IOException e) {
 180             // Probably a permission error, but we're not
 181             // going to check unless a specific permission exception
 182             // is defined.
 183             System.out.println(e);
 184         }
 185         if (!expectSupport) {
 186             throw new RuntimeException("Test failed: " +
 187                     "UnsupportedOperationException was not thrown");
 188         }
 189     }
 190 
 191     private static boolean checkExpectedOptionSupport() {
 192         if (Platform.isSolaris()) {
 193             OSVersion solarisVersion = OSVersion.current();
 194             OSVersion solarisVersionToCheck = new OSVersion(11, 2);
 195             if (solarisVersion.compareTo(solarisVersionToCheck) >= 0) {
 196                 System.out.println("This Solaris version (" + solarisVersion
 197                         + ") should support SO_FLOW_SLA option");
 198                 return true;
 199             } else {
 200                 System.out.println("This Solaris version (" + solarisVersion
 201                         + ") should not support SO_FLOW_SLA option");
 202             }
 203         } else {
 204             System.out.println("Not Solaris, SO_FLOW_SLA should not be " +
 205                     "supported");
 206         }
 207         return false;
 208     }
 209 
 210 }