1e573e88e89daf5efb323719c54117c5a423eb245Yi Kong/*
2e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4e573e88e89daf5efb323719c54117c5a423eb245Yi Kong *
5e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * This code is free software; you can redistribute it and/or modify it
6e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * under the terms of the GNU General Public License version 2 only, as
7e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * published by the Free Software Foundation.  Oracle designates this
8e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * particular file as subject to the "Classpath" exception as provided
9e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * by Oracle in the LICENSE file that accompanied this code.
10e573e88e89daf5efb323719c54117c5a423eb245Yi Kong *
11e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * This code is distributed in the hope that it will be useful, but WITHOUT
12e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * version 2 for more details (a copy is included in the LICENSE file that
15e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * accompanied this code).
16e573e88e89daf5efb323719c54117c5a423eb245Yi Kong *
17e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * You should have received a copy of the GNU General Public License version
18e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * 2 along with this work; if not, write to the Free Software Foundation,
19e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20e573e88e89daf5efb323719c54117c5a423eb245Yi Kong *
21e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * or visit www.oracle.com if you need additional information or have any
23e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * questions.
24e573e88e89daf5efb323719c54117c5a423eb245Yi Kong */
25e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
26e573e88e89daf5efb323719c54117c5a423eb245Yi Kongpackage jdk.net;
27e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
28e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.net.*;
29e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.io.IOException;
30e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.io.FileDescriptor;
31e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.security.PrivilegedAction;
32e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.security.AccessController;
33e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.lang.reflect.*;
34e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.util.Set;
35e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.util.HashSet;
36e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.util.HashMap;
37e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport java.util.Collections;
38e573e88e89daf5efb323719c54117c5a423eb245Yi Kongimport sun.net.ExtendedOptionsImpl;
39e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
40e573e88e89daf5efb323719c54117c5a423eb245Yi Kong/**
41e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * Defines static methods to set and get socket options defined by the
42e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * {@link java.net.SocketOption} interface. All of the standard options defined
43e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and
44e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * {@link java.net.DatagramSocket} can be set this way, as well as additional
45e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * or platform specific options supported by each socket type.
46e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * <p>
47e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * The {@link #supportedOptions(Class)} method can be called to determine
48e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * the complete set of options available (per socket type) on the
49e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * current system.
50e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * <p>
51e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * When a security manager is installed, some non-standard socket options
52e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * may require a security permission before being set or get.
53e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * The details are specified in {@link ExtendedSocketOptions}. No permission
54e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * is required for {@link java.net.StandardSocketOptions}.
55e573e88e89daf5efb323719c54117c5a423eb245Yi Kong *
56e573e88e89daf5efb323719c54117c5a423eb245Yi Kong * @see java.nio.channels.NetworkChannel
57e573e88e89daf5efb323719c54117c5a423eb245Yi Kong */
58e573e88e89daf5efb323719c54117c5a423eb245Yi Kong//@jdk.Exported
59e573e88e89daf5efb323719c54117c5a423eb245Yi Kongpublic class Sockets {
60e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
61e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private final static HashMap<Class<?>,Set<SocketOption<?>>>
62e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        options = new HashMap<>();
63e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
64e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    static {
65e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        initOptionSets();
66e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        AccessController.doPrivileged(
67e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            new java.security.PrivilegedAction<Void>() {
68e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                public Void run() {
69e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    initMethods();
70e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    return null;
71e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                }
72e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            }
73e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        );
74e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
75e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
76e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static Method siSetOption;
77e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static Method siGetOption;
78e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static Method dsiSetOption;
79e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static Method dsiGetOption;
80e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
81e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static void initMethods() {
82e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        try {
83e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            Class<?> clazz = Class.forName("java.net.SocketSecrets");
84e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
85e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            siSetOption = clazz.getDeclaredMethod(
86e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                "setOption", Object.class,
87e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                SocketOption.class, Object.class
88e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            );
89e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            siSetOption.setAccessible(true);
90e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
91e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            siGetOption = clazz.getDeclaredMethod(
92e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                "getOption", Object.class, SocketOption.class
93e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            );
94e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            siGetOption.setAccessible(true);
95e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
96e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            dsiSetOption = clazz.getDeclaredMethod(
97e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                "setOption", DatagramSocket.class,
98e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                SocketOption.class, Object.class
99e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            );
100e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            dsiSetOption.setAccessible(true);
101e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
102e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            dsiGetOption = clazz.getDeclaredMethod(
103e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                "getOption", DatagramSocket.class, SocketOption.class
104e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            );
105e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            dsiGetOption.setAccessible(true);
106e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } catch (ReflectiveOperationException e) {
107e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new InternalError(e);
108e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
109e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
110e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
111e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static <T> void invokeSet(
112e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        Method method, Object socket,
113e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        SocketOption<T> option, T value) throws IOException
114e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
115e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        try {
116e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            method.invoke(null, socket, option, value);
117e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } catch (Exception e) {
118e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            if (e instanceof InvocationTargetException) {
119e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                Throwable t = ((InvocationTargetException)e).getTargetException();
120e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                if (t instanceof IOException) {
121e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    throw (IOException)t;
122e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                } else if (t instanceof RuntimeException) {
123e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    throw (RuntimeException)t;
124e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                }
125e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            }
126e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new RuntimeException(e);
127e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
128e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
129e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
130e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static <T> T invokeGet(
131e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        Method method, Object socket, SocketOption<T> option) throws IOException
132e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
133e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        try {
134e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            return (T)method.invoke(null, socket, option);
135e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        } catch (Exception e) {
136e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            if (e instanceof InvocationTargetException) {
137e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                Throwable t = ((InvocationTargetException)e).getTargetException();
138e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                if (t instanceof IOException) {
139e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    throw (IOException)t;
140e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                } else if (t instanceof RuntimeException) {
141e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                    throw (RuntimeException)t;
142e573e88e89daf5efb323719c54117c5a423eb245Yi Kong                }
143e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            }
144e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new RuntimeException(e);
145e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
146e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
147e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
148e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private Sockets() {}
149e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
150e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
151e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Sets the value of a socket option on a {@link java.net.Socket}
152e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
153e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
154e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
155e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param value The value of the socket option. May be null for some
156e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *              options.
157e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
158e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
159e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
160e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
161e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IllegalArgumentException if the value is not valid for
162e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
163e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
164e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs, or socket is closed.
165e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
166e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
167e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
168e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
169e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
170e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
171e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
172e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
173e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException
174e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
175e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(Socket.class, name)) {
176e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
177e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
178e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        invokeSet(siSetOption, s, name, value);
179e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
180e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
181e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
182e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Returns the value of a socket option from a {@link java.net.Socket}
183e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
184e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
185e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
186e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
187e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @return The value of the socket option.
188e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
189e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
190e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
191e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
192e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs
193e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
194e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
195e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
196e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
197e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
198e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
199e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
200e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
201e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException
202e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
203e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(Socket.class, name)) {
204e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
205e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
206e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        return invokeGet(siGetOption, s, name);
207e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
208e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
209e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
210e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Sets the value of a socket option on a {@link java.net.ServerSocket}
211e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
212e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
213e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
214e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param value The value of the socket option.
215e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
216e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
217e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
218e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
219e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IllegalArgumentException if the value is not valid for
220e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
221e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
222e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs
223e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
224e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
225e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
226e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
227e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
228e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
229e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
230e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
231e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException
232e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
233e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(ServerSocket.class, name)) {
234e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
235e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
236e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        invokeSet(siSetOption, s, name, value);
237e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
238e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
239e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
240e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Returns the value of a socket option from a {@link java.net.ServerSocket}
241e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
242e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
243e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
244e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
245e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @return The value of the socket option.
246e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
247e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
248e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
249e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
250e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs
251e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
252e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
253e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
254e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
255e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
256e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
257e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
258e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
259e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException
260e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
261e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(ServerSocket.class, name)) {
262e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
263e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
264e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        return invokeGet(siGetOption, s, name);
265e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
266e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
267e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
268e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Sets the value of a socket option on a {@link java.net.DatagramSocket}
269e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * or {@link java.net.MulticastSocket}
270e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
271e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
272e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
273e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param value The value of the socket option.
274e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
275e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
276e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
277e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
278e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IllegalArgumentException if the value is not valid for
279e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
280e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
281e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs
282e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
283e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
284e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
285e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
286e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
287e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
288e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
289e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
290e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException
291e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
292e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(s.getClass(), name)) {
293e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
294e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
295e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        invokeSet(dsiSetOption, s, name, value);
296e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
297e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
298e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
299e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Returns the value of a socket option from a
300e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket}
301e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
302e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param s the socket
303e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param name The socket option
304e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
305e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @return The value of the socket option.
306e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
307e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws UnsupportedOperationException if the socket does not support
308e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         the option.
309e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
310e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IOException if an I/O error occurs
311e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
312e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws NullPointerException if name is null
313e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
314e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws SecurityException if a security manager is set and the
315e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         caller does not have any required permission.
316e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
317e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @see java.net.StandardSocketOptions
318e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
319e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException
320e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    {
321e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (!isSupported(s.getClass(), name)) {
322e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new UnsupportedOperationException(name.name());
323e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
324e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        return invokeGet(dsiGetOption, s, name);
325e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
326e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
327e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    /**
328e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * Returns a set of {@link java.net.SocketOption}s supported by the
329e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * given socket type. This set may include standard options and also
330e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * non standard extended options.
331e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
332e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @param socketType the type of java.net socket
333e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *
334e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     * @throws IllegalArgumentException if socketType is not a valid
335e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     *         socket type from the java.net package.
336e573e88e89daf5efb323719c54117c5a423eb245Yi Kong     */
337e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) {
338e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        Set<SocketOption<?>> set = options.get(socketType);
339e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (set == null) {
340e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            throw new IllegalArgumentException("unknown socket type");
341e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
342e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        return set;
343e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
344e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
345e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static boolean isSupported(Class<?> type, SocketOption<?> option) {
346e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        Set<SocketOption<?>> options = supportedOptions(type);
347e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        return options.contains(option);
348e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
349e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
350e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    private static void initOptionSets() {
351e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        boolean flowsupported = ExtendedOptionsImpl.flowSupported();
352e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
353e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        // Socket
354e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
355e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        Set<SocketOption<?>> set = new HashSet<>();
356e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_KEEPALIVE);
357e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_SNDBUF);
358e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_RCVBUF);
359e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_REUSEADDR);
360e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_LINGER);
361e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_TOS);
362e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.TCP_NODELAY);
363e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (flowsupported) {
364e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
365e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
366e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = Collections.unmodifiableSet(set);
367e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        options.put(Socket.class, set);
368e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
369e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        // ServerSocket
370e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
371e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = new HashSet<>();
372e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_RCVBUF);
373e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_REUSEADDR);
374e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_TOS);
375e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = Collections.unmodifiableSet(set);
376e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        options.put(ServerSocket.class, set);
377e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
378e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        // DatagramSocket
379e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
380e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = new HashSet<>();
381e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_SNDBUF);
382e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_RCVBUF);
383e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_REUSEADDR);
384e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_TOS);
385e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (flowsupported) {
386e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
387e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
388e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = Collections.unmodifiableSet(set);
389e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        options.put(DatagramSocket.class, set);
390e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
391e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        // MulticastSocket
392e573e88e89daf5efb323719c54117c5a423eb245Yi Kong
393e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = new HashSet<>();
394e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_SNDBUF);
395e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_RCVBUF);
396e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.SO_REUSEADDR);
397e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_TOS);
398e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_MULTICAST_IF);
399e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_MULTICAST_TTL);
400e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
401e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        if (flowsupported) {
402e573e88e89daf5efb323719c54117c5a423eb245Yi Kong            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
403e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        }
404e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        set = Collections.unmodifiableSet(set);
405e573e88e89daf5efb323719c54117c5a423eb245Yi Kong        options.put(MulticastSocket.class, set);
406e573e88e89daf5efb323719c54117c5a423eb245Yi Kong    }
407e573e88e89daf5efb323719c54117c5a423eb245Yi Kong}
408