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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.net; 27 28 import java.net.*; 29 import java.io.IOException; 30 import java.io.FileDescriptor; 31 import java.security.PrivilegedAction; 32 import java.security.AccessController; 33 import java.lang.reflect.Field; 34 import java.util.Set; 35 import java.util.HashSet; 36 import java.util.HashMap; 37 import java.util.Collections; 38 import sun.net.ExtendedOptionsImpl; 39 40 /** 41 * Defines static methods to set and get socket options defined by the 42 * {@link java.net.SocketOption} interface. All of the standard options defined 43 * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and 44 * {@link java.net.DatagramSocket} can be set this way, as well as additional 45 * or platform specific options supported by each socket type. 46 * <p> 47 * The {@link #supportedOptions(Class)} method can be called to determine 48 * the complete set of options available (per socket type) on the 49 * current system. 50 * <p> 51 * When a security manager is installed, some non-standard socket options 52 * may require a security permission before being set or get. 53 * The details are specified in {@link ExtendedSocketOptions}. No permission 54 * is required for {@link java.net.StandardSocketOptions}. 55 * 56 * @see java.nio.channels.NetworkChannel 57 */ 58 @jdk.Exported 59 public class Sockets { 60 61 private static final HashMap<Class<?>,Set<SocketOption<?>>> 62 options = new HashMap<>(); 63 64 static { 65 initOptionSets(); 66 } 67 68 private Sockets() {} 69 70 /** 71 * Sets the value of a socket option on a {@link java.net.Socket} 72 * 73 * @param s the socket 74 * @param name The socket option 75 * @param value The value of the socket option. May be null for some 76 * options. 77 * 78 * @throws UnsupportedOperationException if the socket does not support 79 * the option. 80 * 81 * @throws IllegalArgumentException if the value is not valid for 82 * the option. 83 * 84 * @throws IOException if an I/O error occurs, or socket is closed. 85 * 86 * @throws SecurityException if a security manager is set and the 87 * caller does not have any required permission. 88 * 89 * @throws NullPointerException if name is null 90 * 91 * @see java.net.StandardSocketOptions 92 */ 93 public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException 94 { 95 s.setOption(name, value); 96 } 97 98 /** 99 * Returns the value of a socket option from a {@link java.net.Socket} 100 * 101 * @param s the socket 102 * @param name The socket option 103 * 104 * @return The value of the socket option. 105 * 106 * @throws UnsupportedOperationException if the socket does not support 107 * the option. 108 * 109 * @throws IOException if an I/O error occurs 110 * 111 * @throws SecurityException if a security manager is set and the 112 * caller does not have any required permission. 113 * 114 * @throws NullPointerException if name is null 115 * 116 * @see java.net.StandardSocketOptions 117 */ 118 public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException 119 { 120 return s.getOption(name); 121 } 122 123 /** 124 * Sets the value of a socket option on a {@link java.net.ServerSocket} 125 * 126 * @param s the socket 127 * @param name The socket option 128 * @param value The value of the socket option. 129 * 130 * @throws UnsupportedOperationException if the socket does not support 131 * the option. 132 * 133 * @throws IllegalArgumentException if the value is not valid for 134 * the option. 135 * 136 * @throws IOException if an I/O error occurs 137 * 138 * @throws NullPointerException if name is null 139 * 140 * @throws SecurityException if a security manager is set and the 141 * caller does not have any required permission. 142 * 143 * @see java.net.StandardSocketOptions 144 */ 145 public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException 146 { 147 s.setOption(name, value); 148 } 149 150 /** 151 * Returns the value of a socket option from a {@link java.net.ServerSocket} 152 * 153 * @param s the socket 154 * @param name The socket option 155 * 156 * @return The value of the socket option. 157 * 158 * @throws UnsupportedOperationException if the socket does not support 159 * the option. 160 * 161 * @throws IOException if an I/O error occurs 162 * 163 * @throws NullPointerException if name is null 164 * 165 * @throws SecurityException if a security manager is set and the 166 * caller does not have any required permission. 167 * 168 * @see java.net.StandardSocketOptions 169 */ 170 public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException 171 { 172 return s.getOption(name); 173 } 174 175 /** 176 * Sets the value of a socket option on a {@link java.net.DatagramSocket} 177 * or {@link java.net.MulticastSocket} 178 * 179 * @param s the socket 180 * @param name The socket option 181 * @param value The value of the socket option. 182 * 183 * @throws UnsupportedOperationException if the socket does not support 184 * the option. 185 * 186 * @throws IllegalArgumentException if the value is not valid for 187 * the option. 188 * 189 * @throws IOException if an I/O error occurs 190 * 191 * @throws NullPointerException if name is null 192 * 193 * @throws SecurityException if a security manager is set and the 194 * caller does not have any required permission. 195 * 196 * @see java.net.StandardSocketOptions 197 */ 198 public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException 199 { 200 s.setOption(name, value); 201 } 202 203 /** 204 * Returns the value of a socket option from a 205 * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} 206 * 207 * @param s the socket 208 * @param name The socket option 209 * 210 * @return The value of the socket option. 211 * 212 * @throws UnsupportedOperationException if the socket does not support 213 * the option. 214 * 215 * @throws IOException if an I/O error occurs 216 * 217 * @throws NullPointerException if name is null 218 * 219 * @throws SecurityException if a security manager is set and the 220 * caller does not have any required permission. 221 * 222 * @see java.net.StandardSocketOptions 223 */ 224 public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException 225 { 226 return s.getOption(name); 227 } 228 229 /** 230 * Returns a set of {@link java.net.SocketOption}s supported by the 231 * given socket type. This set may include standard options and also 232 * non standard extended options. 233 * 234 * @param socketType the type of java.net socket 235 * 236 * @throws IllegalArgumentException if socketType is not a valid 237 * socket type from the java.net package. 238 */ 239 public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) { 240 Set<SocketOption<?>> set = options.get(socketType); 241 if (set == null) { 242 throw new IllegalArgumentException("unknown socket type"); 243 } 244 return set; 245 } 246 247 private static void checkValueType(Object value, Class<?> type) { 248 if (!type.isAssignableFrom(value.getClass())) { 249 String s = "Found: " + value.getClass().toString() + " Expected: " 250 + type.toString(); 251 throw new IllegalArgumentException(s); 252 } 253 } 254 255 private static void initOptionSets() { 256 boolean flowsupported = ExtendedOptionsImpl.flowSupported(); 257 boolean reuseportsupported = ExtendedOptionsImpl.reuseportSupported(); 258 259 // Socket 260 261 Set<SocketOption<?>> set = new HashSet<>(); 262 set.add(StandardSocketOptions.SO_KEEPALIVE); 263 set.add(StandardSocketOptions.SO_SNDBUF); 264 set.add(StandardSocketOptions.SO_RCVBUF); 265 set.add(StandardSocketOptions.SO_REUSEADDR); 266 set.add(StandardSocketOptions.SO_LINGER); 267 set.add(StandardSocketOptions.IP_TOS); 268 set.add(StandardSocketOptions.TCP_NODELAY); 269 if (flowsupported) { 270 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 271 } 272 if (reuseportsupported) { 273 set.add(ExtendedSocketOptions.SO_REUSEPORT); 274 } 275 set = Collections.unmodifiableSet(set); 276 options.put(Socket.class, set); 277 278 // ServerSocket 279 280 set = new HashSet<>(); 281 set.add(StandardSocketOptions.SO_RCVBUF); 282 set.add(StandardSocketOptions.SO_REUSEADDR); 283 set.add(StandardSocketOptions.IP_TOS); 284 if (reuseportsupported) { 285 set.add(ExtendedSocketOptions.SO_REUSEPORT); 286 } 287 set = Collections.unmodifiableSet(set); 288 options.put(ServerSocket.class, set); 289 290 // DatagramSocket 291 292 set = new HashSet<>(); 293 set.add(StandardSocketOptions.SO_SNDBUF); 294 set.add(StandardSocketOptions.SO_RCVBUF); 295 set.add(StandardSocketOptions.SO_REUSEADDR); 296 set.add(StandardSocketOptions.IP_TOS); 297 if (flowsupported) { 298 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 299 } 300 if (reuseportsupported) { 301 set.add(ExtendedSocketOptions.SO_REUSEPORT); 302 } 303 set = Collections.unmodifiableSet(set); 304 options.put(DatagramSocket.class, set); 305 306 // MulticastSocket 307 308 set = new HashSet<>(); 309 set.add(StandardSocketOptions.SO_SNDBUF); 310 set.add(StandardSocketOptions.SO_RCVBUF); 311 set.add(StandardSocketOptions.SO_REUSEADDR); 312 set.add(StandardSocketOptions.IP_TOS); 313 set.add(StandardSocketOptions.IP_MULTICAST_IF); 314 set.add(StandardSocketOptions.IP_MULTICAST_TTL); 315 set.add(StandardSocketOptions.IP_MULTICAST_LOOP); 316 if (flowsupported) { 317 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 318 } 319 if (reuseportsupported) { 320 set.add(ExtendedSocketOptions.SO_REUSEPORT); 321 } 322 set = Collections.unmodifiableSet(set); 323 options.put(MulticastSocket.class, set); 324 } 325 }