1 /* 2 * Copyright (c) 2014, 2016, 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 public class Sockets { 59 60 private static final HashMap<Class<?>,Set<SocketOption<?>>> 61 options = new HashMap<>(); 62 63 static { 64 initOptionSets(); 65 } 66 67 private Sockets() {} 68 69 /** 70 * Sets the value of a socket option on a {@link java.net.Socket} 71 * 72 * @param s the socket 73 * @param name The socket option 74 * @param value The value of the socket option. May be null for some 75 * options. 76 * 77 * @throws UnsupportedOperationException if the socket does not support 78 * the option. 79 * 80 * @throws IllegalArgumentException if the value is not valid for 81 * the option. 82 * 83 * @throws IOException if an I/O error occurs, or socket is closed. 84 * 85 * @throws SecurityException if a security manager is set and the 86 * caller does not have any required permission. 87 * 88 * @throws NullPointerException if name is null 89 * 90 * @see java.net.StandardSocketOptions 91 */ 92 public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException 93 { 94 s.setOption(name, value); 95 } 96 97 /** 98 * Returns the value of a socket option from a {@link java.net.Socket} 99 * 100 * @param s the socket 101 * @param name The socket option 102 * 103 * @return The value of the socket option. 104 * 105 * @throws UnsupportedOperationException if the socket does not support 106 * the option. 107 * 108 * @throws IOException if an I/O error occurs 109 * 110 * @throws SecurityException if a security manager is set and the 111 * caller does not have any required permission. 112 * 113 * @throws NullPointerException if name is null 114 * 115 * @see java.net.StandardSocketOptions 116 */ 117 public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException 118 { 119 return s.getOption(name); 120 } 121 122 /** 123 * Sets the value of a socket option on a {@link java.net.ServerSocket} 124 * 125 * @param s the socket 126 * @param name The socket option 127 * @param value The value of the socket option. 128 * 129 * @throws UnsupportedOperationException if the socket does not support 130 * the option. 131 * 132 * @throws IllegalArgumentException if the value is not valid for 133 * the option. 134 * 135 * @throws IOException if an I/O error occurs 136 * 137 * @throws NullPointerException if name is null 138 * 139 * @throws SecurityException if a security manager is set and the 140 * caller does not have any required permission. 141 * 142 * @see java.net.StandardSocketOptions 143 */ 144 public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException 145 { 146 s.setOption(name, value); 147 } 148 149 /** 150 * Returns the value of a socket option from a {@link java.net.ServerSocket} 151 * 152 * @param s the socket 153 * @param name The socket option 154 * 155 * @return The value of the socket option. 156 * 157 * @throws UnsupportedOperationException if the socket does not support 158 * the option. 159 * 160 * @throws IOException if an I/O error occurs 161 * 162 * @throws NullPointerException if name is null 163 * 164 * @throws SecurityException if a security manager is set and the 165 * caller does not have any required permission. 166 * 167 * @see java.net.StandardSocketOptions 168 */ 169 public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException 170 { 171 return s.getOption(name); 172 } 173 174 /** 175 * Sets the value of a socket option on a {@link java.net.DatagramSocket} 176 * or {@link java.net.MulticastSocket} 177 * 178 * @param s the socket 179 * @param name The socket option 180 * @param value The value of the socket option. 181 * 182 * @throws UnsupportedOperationException if the socket does not support 183 * the option. 184 * 185 * @throws IllegalArgumentException if the value is not valid for 186 * the option. 187 * 188 * @throws IOException if an I/O error occurs 189 * 190 * @throws NullPointerException if name is null 191 * 192 * @throws SecurityException if a security manager is set and the 193 * caller does not have any required permission. 194 * 195 * @see java.net.StandardSocketOptions 196 */ 197 public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException 198 { 199 s.setOption(name, value); 200 } 201 202 /** 203 * Returns the value of a socket option from a 204 * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket} 205 * 206 * @param s the socket 207 * @param name The socket option 208 * 209 * @return The value of the socket option. 210 * 211 * @throws UnsupportedOperationException if the socket does not support 212 * the option. 213 * 214 * @throws IOException if an I/O error occurs 215 * 216 * @throws NullPointerException if name is null 217 * 218 * @throws SecurityException if a security manager is set and the 219 * caller does not have any required permission. 220 * 221 * @see java.net.StandardSocketOptions 222 */ 223 public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException 224 { 225 return s.getOption(name); 226 } 227 228 /** 229 * Returns a set of {@link java.net.SocketOption}s supported by the 230 * given socket type. This set may include standard options and also 231 * non standard extended options. 232 * 233 * @param socketType the type of java.net socket 234 * 235 * @throws IllegalArgumentException if socketType is not a valid 236 * socket type from the java.net package. 237 */ 238 public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) { 239 Set<SocketOption<?>> set = options.get(socketType); 240 if (set == null) { 241 throw new IllegalArgumentException("unknown socket type"); 242 } 243 return set; 244 } 245 246 private static void checkValueType(Object value, Class<?> type) { 247 if (!type.isAssignableFrom(value.getClass())) { 248 String s = "Found: " + value.getClass().toString() + " Expected: " 249 + type.toString(); 250 throw new IllegalArgumentException(s); 251 } 252 } 253 254 private static void initOptionSets() { 255 boolean flowsupported = ExtendedOptionsImpl.flowSupported(); 256 boolean quickAckSupported = ExtendedOptionsImpl.isQuickAckAvailable(); 257 258 // Socket 259 260 Set<SocketOption<?>> set = new HashSet<>(); 261 set.add(StandardSocketOptions.SO_KEEPALIVE); 262 set.add(StandardSocketOptions.SO_SNDBUF); 263 set.add(StandardSocketOptions.SO_RCVBUF); 264 set.add(StandardSocketOptions.SO_REUSEADDR); 265 set.add(StandardSocketOptions.SO_LINGER); 266 set.add(StandardSocketOptions.IP_TOS); 267 set.add(StandardSocketOptions.TCP_NODELAY); 268 if (flowsupported) { 269 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 270 } 271 if (quickAckSupported) { 272 set.add(ExtendedSocketOptions.SO_QUICKACK); 273 } 274 set = Collections.unmodifiableSet(set); 275 options.put(Socket.class, set); 276 277 // ServerSocket 278 279 set = new HashSet<>(); 280 set.add(StandardSocketOptions.SO_RCVBUF); 281 set.add(StandardSocketOptions.SO_REUSEADDR); 282 set.add(StandardSocketOptions.IP_TOS); 283 set = Collections.unmodifiableSet(set); 284 options.put(ServerSocket.class, set); 285 286 // DatagramSocket 287 288 set = new HashSet<>(); 289 set.add(StandardSocketOptions.SO_SNDBUF); 290 set.add(StandardSocketOptions.SO_RCVBUF); 291 set.add(StandardSocketOptions.SO_REUSEADDR); 292 set.add(StandardSocketOptions.IP_TOS); 293 if (flowsupported) { 294 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 295 } 296 if (quickAckSupported) { 297 set.add(ExtendedSocketOptions.SO_QUICKACK); 298 } 299 set = Collections.unmodifiableSet(set); 300 options.put(DatagramSocket.class, set); 301 302 // MulticastSocket 303 304 set = new HashSet<>(); 305 set.add(StandardSocketOptions.SO_SNDBUF); 306 set.add(StandardSocketOptions.SO_RCVBUF); 307 set.add(StandardSocketOptions.SO_REUSEADDR); 308 set.add(StandardSocketOptions.IP_TOS); 309 set.add(StandardSocketOptions.IP_MULTICAST_IF); 310 set.add(StandardSocketOptions.IP_MULTICAST_TTL); 311 set.add(StandardSocketOptions.IP_MULTICAST_LOOP); 312 if (flowsupported) { 313 set.add(ExtendedSocketOptions.SO_FLOW_SLA); 314 } 315 if (quickAckSupported) { 316 set.add(ExtendedSocketOptions.SO_QUICKACK); 317 } 318 set = Collections.unmodifiableSet(set); 319 options.put(MulticastSocket.class, set); 320 } 321 }