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