1 /* 2 * Copyright (c) 2007, 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 /* @test 25 * @bug 4640544 8044773 8233435 26 * @summary Unit test for setOption/getOption/options methods 27 * @requires !vm.graal.enabled 28 * @library /test/lib 29 * @build jdk.test.lib.net.IPSupport 30 * jdk.test.lib.NetworkConfiguration 31 * SocketOptionTests 32 * @run main SocketOptionTests 33 * @run main/othervm -Djava.net.preferIPv4Stack=true SocketOptionTests 34 * @run main/othervm --limit-modules=java.base SocketOptionTests 35 */ 36 37 import java.nio.*; 38 import java.nio.channels.*; 39 import java.net.*; 40 import java.io.IOException; 41 import java.util.*; 42 import static java.net.StandardProtocolFamily.*; 43 import static java.net.StandardSocketOptions.*; 44 45 import jdk.test.lib.NetworkConfiguration; 46 import jdk.test.lib.net.IPSupport; 47 48 public class SocketOptionTests { 49 main(String[] args)50 public static void main(String[] args) throws IOException { 51 IPSupport.throwSkippedExceptionIfNonOperational(); 52 53 NetworkConfiguration config = NetworkConfiguration.probe(); 54 InetAddress ip4Address = config.ip4Addresses().findAny().orElse(null); 55 InetAddress ip6Address = config.ip6Addresses().findAny().orElse(null); 56 57 System.out.println("[UNSPEC, bound to wildcard address]"); 58 try (DatagramChannel dc = DatagramChannel.open()) { 59 test(dc, new InetSocketAddress(0)); 60 } 61 62 if (IPSupport.hasIPv4()) { 63 System.out.println("[INET, bound to wildcard address]"); 64 try (DatagramChannel dc = DatagramChannel.open(INET)) { 65 test(dc, new InetSocketAddress(0)); 66 } 67 System.out.println("[INET, bound to IPv4 address]"); 68 try (DatagramChannel dc = DatagramChannel.open(INET)) { 69 test(dc, new InetSocketAddress(ip4Address, 0)); 70 } 71 } 72 73 if (IPSupport.hasIPv6()) { 74 System.out.println("[INET6, bound to wildcard address]"); 75 try (DatagramChannel dc = DatagramChannel.open(INET6)) { 76 test(dc, new InetSocketAddress(0)); 77 } 78 System.out.println("[INET6, bound to IPv6 address]"); 79 try (DatagramChannel dc = DatagramChannel.open(INET6)) { 80 test(dc, new InetSocketAddress(ip6Address, 0)); 81 } 82 } 83 84 if (IPSupport.hasIPv4() && IPSupport.hasIPv6()) { 85 System.out.println("[UNSPEC, bound to IPv4 address]"); 86 try (DatagramChannel dc = DatagramChannel.open()) { 87 test(dc, new InetSocketAddress(ip4Address, 0)); 88 } 89 System.out.println("[INET6, bound to IPv4 address]"); 90 try (DatagramChannel dc = DatagramChannel.open(INET6)) { 91 test(dc, new InetSocketAddress(ip4Address, 0)); 92 } 93 } 94 } 95 test(DatagramChannel dc, SocketAddress localAddress)96 static void test(DatagramChannel dc, SocketAddress localAddress) throws IOException { 97 // check supported options 98 Set<SocketOption<?>> options = dc.supportedOptions(); 99 boolean reuseport = options.contains(SO_REUSEPORT); 100 List<? extends SocketOption<?>> expected; 101 if (reuseport) { 102 expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, 103 SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, 104 IP_MULTICAST_TTL, IP_MULTICAST_LOOP); 105 } else { 106 expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, 107 SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, 108 IP_MULTICAST_LOOP); 109 } 110 for (SocketOption opt: expected) { 111 if (!options.contains(opt)) 112 throw new RuntimeException(opt.name() + " should be supported"); 113 } 114 115 // check specified defaults 116 checkOption(dc, SO_BROADCAST, false); 117 checkOption(dc, IP_MULTICAST_TTL, 1); // true on supported platforms 118 checkOption(dc, IP_MULTICAST_LOOP, true); // true on supported platforms 119 120 // allowed to change when not bound 121 dc.setOption(SO_BROADCAST, true); 122 checkOption(dc, SO_BROADCAST, true); 123 dc.setOption(SO_BROADCAST, false); 124 checkOption(dc, SO_BROADCAST, false); 125 dc.setOption(SO_SNDBUF, 128*1024); // can't check 126 dc.setOption(SO_RCVBUF, 128*1024); // can't check 127 int before, after; 128 before = dc.getOption(SO_SNDBUF); 129 after = dc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF); 130 if (after < before) 131 throw new RuntimeException("setOption caused SO_SNDBUF to decrease"); 132 before = dc.getOption(SO_RCVBUF); 133 after = dc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); 134 if (after < before) 135 throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); 136 dc.setOption(SO_REUSEADDR, true); 137 checkOption(dc, SO_REUSEADDR, true); 138 dc.setOption(SO_REUSEADDR, false); 139 checkOption(dc, SO_REUSEADDR, false); 140 if (reuseport) { 141 dc.setOption(SO_REUSEPORT, true); 142 checkOption(dc, SO_REUSEPORT, true); 143 dc.setOption(SO_REUSEPORT, false); 144 checkOption(dc, SO_REUSEPORT, false); 145 } 146 // bind socket 147 dc.bind(localAddress); 148 149 // allow to change when bound 150 dc.setOption(SO_BROADCAST, true); 151 checkOption(dc, SO_BROADCAST, true); 152 dc.setOption(SO_BROADCAST, false); 153 checkOption(dc, SO_BROADCAST, false); 154 dc.setOption(IP_TOS, 0x08); // can't check 155 dc.setOption(IP_MULTICAST_TTL, 2); 156 checkOption(dc, IP_MULTICAST_TTL, 2); 157 dc.setOption(IP_MULTICAST_LOOP, false); 158 checkOption(dc, IP_MULTICAST_LOOP, false); 159 dc.setOption(IP_MULTICAST_LOOP, true); 160 checkOption(dc, IP_MULTICAST_LOOP, true); 161 162 // NullPointerException 163 try { 164 dc.setOption(null, "value"); 165 throw new RuntimeException("NullPointerException not thrown"); 166 } catch (NullPointerException x) { 167 } 168 try { 169 dc.getOption(null); 170 throw new RuntimeException("NullPointerException not thrown"); 171 } catch (NullPointerException x) { 172 } 173 174 // ClosedChannelException 175 dc.close(); 176 try { 177 dc.setOption(IP_MULTICAST_LOOP, true); 178 throw new RuntimeException("ClosedChannelException not thrown"); 179 } catch (ClosedChannelException x) { 180 } 181 } 182 checkOption(DatagramChannel dc, SocketOption<T> name, T expectedValue)183 static <T> void checkOption(DatagramChannel dc, 184 SocketOption<T> name, 185 T expectedValue) 186 throws IOException 187 { 188 T value = dc.getOption(name); 189 if (!value.equals(expectedValue)) 190 throw new RuntimeException("value not as expected"); 191 } 192 } 193