1 /*
2  * Copyright (c) 1995, 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.  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 java.net;
27 
28 import java.io.IOException;
29 import java.nio.channels.DatagramChannel;
30 import java.security.AccessController;
31 import java.security.PrivilegedExceptionAction;
32 import java.util.Objects;
33 import java.util.Set;
34 import java.util.Collections;
35 
36 /**
37  * This class represents a socket for sending and receiving datagram packets.
38  *
39  * <p>A datagram socket is the sending or receiving point for a packet
40  * delivery service. Each packet sent or received on a datagram socket
41  * is individually addressed and routed. Multiple packets sent from
42  * one machine to another may be routed differently, and may arrive in
43  * any order.
44  *
45  * <p> Where possible, a newly constructed {@code DatagramSocket} has the
46  * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
47  * to allow the transmission of broadcast datagrams. In order to receive
48  * broadcast packets a DatagramSocket should be bound to the wildcard address.
49  * In some implementations, broadcast packets may also be received when
50  * a DatagramSocket is bound to a more specific address.
51  * <p>
52  * Example:
53  * {@code
54  *              DatagramSocket s = new DatagramSocket(null);
55  *              s.bind(new InetSocketAddress(8888));
56  * }
57  * Which is equivalent to:
58  * {@code
59  *              DatagramSocket s = new DatagramSocket(8888);
60  * }
61  * Both cases will create a DatagramSocket able to receive broadcasts on
62  * UDP port 8888.
63  *
64  * @author  Pavani Diwanji
65  * @see     java.net.DatagramPacket
66  * @see     java.nio.channels.DatagramChannel
67  * @since 1.0
68  */
69 public
70 class DatagramSocket implements java.io.Closeable {
71     /**
72      * Various states of this socket.
73      */
74     private boolean created = false;
75     private boolean bound = false;
76     private boolean closed = false;
77     private Object closeLock = new Object();
78 
79     /*
80      * The implementation of this DatagramSocket.
81      */
82     DatagramSocketImpl impl;
83 
84     /**
85      * Are we using an older DatagramSocketImpl?
86      */
87     boolean oldImpl = false;
88 
89     /**
90      * Set when a socket is ST_CONNECTED until we are certain
91      * that any packets which might have been received prior
92      * to calling connect() but not read by the application
93      * have been read. During this time we check the source
94      * address of all packets received to be sure they are from
95      * the connected destination. Other packets are read but
96      * silently dropped.
97      */
98     private boolean explicitFilter = false;
99     private int bytesLeftToFilter;
100     /*
101      * Connection state:
102      * ST_NOT_CONNECTED = socket not connected
103      * ST_CONNECTED = socket connected
104      * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
105      */
106     static final int ST_NOT_CONNECTED = 0;
107     static final int ST_CONNECTED = 1;
108     static final int ST_CONNECTED_NO_IMPL = 2;
109 
110     int connectState = ST_NOT_CONNECTED;
111 
112     /*
113      * Connected address & port
114      */
115     InetAddress connectedAddress = null;
116     int connectedPort = -1;
117 
118     /**
119      * Connects this socket to a remote socket address (IP address + port number).
120      * Binds socket if not already bound.
121      *
122      * @param   address The remote address.
123      * @param   port    The remote port
124      * @throws  SocketException if binding the socket fails.
125      */
connectInternal(InetAddress address, int port)126     private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
127         if (port < 0 || port > 0xFFFF) {
128             throw new IllegalArgumentException("connect: " + port);
129         }
130         if (address == null) {
131             throw new IllegalArgumentException("connect: null address");
132         }
133         checkAddress (address, "connect");
134         if (isClosed())
135             return;
136         SecurityManager security = System.getSecurityManager();
137         if (security != null) {
138             if (address.isMulticastAddress()) {
139                 security.checkMulticast(address);
140             } else {
141                 security.checkConnect(address.getHostAddress(), port);
142                 security.checkAccept(address.getHostAddress(), port);
143             }
144         }
145 
146         if (!isBound())
147           bind(new InetSocketAddress(0));
148 
149         // old impls do not support connect/disconnect
150         if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
151              ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
152             connectState = ST_CONNECTED_NO_IMPL;
153         } else {
154             try {
155                 getImpl().connect(address, port);
156 
157                 // socket is now connected by the impl
158                 connectState = ST_CONNECTED;
159                 // Do we need to filter some packets?
160                 int avail = getImpl().dataAvailable();
161                 if (avail == -1) {
162                     throw new SocketException();
163                 }
164                 explicitFilter = avail > 0;
165                 if (explicitFilter) {
166                     bytesLeftToFilter = getReceiveBufferSize();
167                 }
168             } catch (SocketException se) {
169 
170                 // connection will be emulated by DatagramSocket
171                 connectState = ST_CONNECTED_NO_IMPL;
172             }
173         }
174 
175         connectedAddress = address;
176         connectedPort = port;
177     }
178 
179 
180     /**
181      * Constructs a datagram socket and binds it to any available port
182      * on the local host machine.  The socket will be bound to the
183      * {@link InetAddress#isAnyLocalAddress wildcard} address,
184      * an IP address chosen by the kernel.
185      *
186      * <p>If there is a security manager,
187      * its {@code checkListen} method is first called
188      * with 0 as its argument to ensure the operation is allowed.
189      * This could result in a SecurityException.
190      *
191      * @exception  SocketException  if the socket could not be opened,
192      *               or the socket could not bind to the specified local port.
193      * @exception  SecurityException  if a security manager exists and its
194      *             {@code checkListen} method doesn't allow the operation.
195      *
196      * @see SecurityManager#checkListen
197      */
DatagramSocket()198     public DatagramSocket() throws SocketException {
199         this(new InetSocketAddress(0));
200     }
201 
202     /**
203      * Creates an unbound datagram socket with the specified
204      * DatagramSocketImpl.
205      *
206      * @param impl an instance of a <B>DatagramSocketImpl</B>
207      *        the subclass wishes to use on the DatagramSocket.
208      * @since   1.4
209      */
DatagramSocket(DatagramSocketImpl impl)210     protected DatagramSocket(DatagramSocketImpl impl) {
211         if (impl == null)
212             throw new NullPointerException();
213         this.impl = impl;
214         checkOldImpl();
215     }
216 
217     /**
218      * Creates a datagram socket, bound to the specified local
219      * socket address.
220      * <p>
221      * If, if the address is {@code null}, creates an unbound socket.
222      *
223      * <p>If there is a security manager,
224      * its {@code checkListen} method is first called
225      * with the port from the socket address
226      * as its argument to ensure the operation is allowed.
227      * This could result in a SecurityException.
228      *
229      * @param bindaddr local socket address to bind, or {@code null}
230      *                 for an unbound socket.
231      *
232      * @exception  SocketException  if the socket could not be opened,
233      *               or the socket could not bind to the specified local port.
234      * @exception  SecurityException  if a security manager exists and its
235      *             {@code checkListen} method doesn't allow the operation.
236      *
237      * @see SecurityManager#checkListen
238      * @since   1.4
239      */
DatagramSocket(SocketAddress bindaddr)240     public DatagramSocket(SocketAddress bindaddr) throws SocketException {
241         // create a datagram socket.
242         createImpl();
243         if (bindaddr != null) {
244             try {
245                 bind(bindaddr);
246             } finally {
247                 if (!isBound())
248                     close();
249             }
250         }
251     }
252 
253     /**
254      * Constructs a datagram socket and binds it to the specified port
255      * on the local host machine.  The socket will be bound to the
256      * {@link InetAddress#isAnyLocalAddress wildcard} address,
257      * an IP address chosen by the kernel.
258      *
259      * <p>If there is a security manager,
260      * its {@code checkListen} method is first called
261      * with the {@code port} argument
262      * as its argument to ensure the operation is allowed.
263      * This could result in a SecurityException.
264      *
265      * @param      port port to use.
266      * @exception  SocketException  if the socket could not be opened,
267      *               or the socket could not bind to the specified local port.
268      * @exception  SecurityException  if a security manager exists and its
269      *             {@code checkListen} method doesn't allow the operation.
270      *
271      * @see SecurityManager#checkListen
272      */
DatagramSocket(int port)273     public DatagramSocket(int port) throws SocketException {
274         this(port, null);
275     }
276 
277     /**
278      * Creates a datagram socket, bound to the specified local
279      * address.  The local port must be between 0 and 65535 inclusive.
280      * If the IP address is 0.0.0.0, the socket will be bound to the
281      * {@link InetAddress#isAnyLocalAddress wildcard} address,
282      * an IP address chosen by the kernel.
283      *
284      * <p>If there is a security manager,
285      * its {@code checkListen} method is first called
286      * with the {@code port} argument
287      * as its argument to ensure the operation is allowed.
288      * This could result in a SecurityException.
289      *
290      * @param port local port to use
291      * @param laddr local address to bind
292      *
293      * @exception  SocketException  if the socket could not be opened,
294      *               or the socket could not bind to the specified local port.
295      * @exception  SecurityException  if a security manager exists and its
296      *             {@code checkListen} method doesn't allow the operation.
297      *
298      * @see SecurityManager#checkListen
299      * @since   1.1
300      */
DatagramSocket(int port, InetAddress laddr)301     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
302         this(new InetSocketAddress(laddr, port));
303     }
304 
checkOldImpl()305     private void checkOldImpl() {
306         if (impl == null)
307             return;
308         // DatagramSocketImpl.peekData() is a protected method, therefore we need to use
309         // getDeclaredMethod, therefore we need permission to access the member
310         try {
311             AccessController.doPrivileged(
312                 new PrivilegedExceptionAction<>() {
313                     public Void run() throws NoSuchMethodException {
314                         Class<?>[] cl = new Class<?>[1];
315                         cl[0] = DatagramPacket.class;
316                         impl.getClass().getDeclaredMethod("peekData", cl);
317                         return null;
318                     }
319                 });
320         } catch (java.security.PrivilegedActionException e) {
321             oldImpl = true;
322         }
323     }
324 
325     static Class<?> implClass = null;
326 
createImpl()327     void createImpl() throws SocketException {
328         if (impl == null) {
329             if (factory != null) {
330                 impl = factory.createDatagramSocketImpl();
331                 checkOldImpl();
332             } else {
333                 boolean isMulticast = (this instanceof MulticastSocket) ? true : false;
334                 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast);
335 
336                 checkOldImpl();
337             }
338         }
339         // creates a udp socket
340         impl.create();
341         impl.setDatagramSocket(this);
342         created = true;
343     }
344 
345     /**
346      * Get the {@code DatagramSocketImpl} attached to this socket,
347      * creating it if necessary.
348      *
349      * @return  the {@code DatagramSocketImpl} attached to that
350      *          DatagramSocket
351      * @throws SocketException if creation fails.
352      * @since 1.4
353      */
getImpl()354     DatagramSocketImpl getImpl() throws SocketException {
355         if (!created)
356             createImpl();
357         return impl;
358     }
359 
360     /**
361      * Binds this DatagramSocket to a specific address and port.
362      * <p>
363      * If the address is {@code null}, then the system will pick up
364      * an ephemeral port and a valid local address to bind the socket.
365      *
366      * @param   addr The address and port to bind to.
367      * @throws  SocketException if any error happens during the bind, or if the
368      *          socket is already bound.
369      * @throws  SecurityException  if a security manager exists and its
370      *             {@code checkListen} method doesn't allow the operation.
371      * @throws IllegalArgumentException if addr is a SocketAddress subclass
372      *         not supported by this socket.
373      * @since 1.4
374      */
bind(SocketAddress addr)375     public synchronized void bind(SocketAddress addr) throws SocketException {
376         if (isClosed())
377             throw new SocketException("Socket is closed");
378         if (isBound())
379             throw new SocketException("already bound");
380         if (addr == null)
381             addr = new InetSocketAddress(0);
382         if (!(addr instanceof InetSocketAddress))
383             throw new IllegalArgumentException("Unsupported address type!");
384         InetSocketAddress epoint = (InetSocketAddress) addr;
385         if (epoint.isUnresolved())
386             throw new SocketException("Unresolved address");
387         InetAddress iaddr = epoint.getAddress();
388         int port = epoint.getPort();
389         checkAddress(iaddr, "bind");
390         SecurityManager sec = System.getSecurityManager();
391         if (sec != null) {
392             sec.checkListen(port);
393         }
394         try {
395             getImpl().bind(port, iaddr);
396         } catch (SocketException e) {
397             getImpl().close();
398             throw e;
399         }
400         bound = true;
401     }
402 
checkAddress(InetAddress addr, String op)403     void checkAddress (InetAddress addr, String op) {
404         if (addr == null) {
405             return;
406         }
407         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
408             throw new IllegalArgumentException(op + ": invalid address type");
409         }
410     }
411 
412     /**
413      * Connects the socket to a remote address for this socket. When a
414      * socket is connected to a remote address, packets may only be
415      * sent to or received from that address. By default a datagram
416      * socket is not connected.
417      *
418      * <p>If the remote destination to which the socket is connected does not
419      * exist, or is otherwise unreachable, and if an ICMP destination unreachable
420      * packet has been received for that address, then a subsequent call to
421      * send or receive may throw a PortUnreachableException. Note, there is no
422      * guarantee that the exception will be thrown.
423      *
424      * <p> If a security manager has been installed then it is invoked to check
425      * access to the remote address. Specifically, if the given {@code address}
426      * is a {@link InetAddress#isMulticastAddress multicast address},
427      * the security manager's {@link
428      * java.lang.SecurityManager#checkMulticast(InetAddress)
429      * checkMulticast} method is invoked with the given {@code address}.
430      * Otherwise, the security manager's {@link
431      * java.lang.SecurityManager#checkConnect(String,int) checkConnect}
432      * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods
433      * are invoked, with the given {@code address} and {@code port}, to
434      * verify that datagrams are permitted to be sent and received
435      * respectively.
436      *
437      * <p> When a socket is connected, {@link #receive receive} and
438      * {@link #send send} <b>will not perform any security checks</b>
439      * on incoming and outgoing packets, other than matching the packet's
440      * and the socket's address and port. On a send operation, if the
441      * packet's address is set and the packet's address and the socket's
442      * address do not match, an {@code IllegalArgumentException} will be
443      * thrown. A socket connected to a multicast address may only be used
444      * to send packets.
445      *
446      * @param address the remote address for the socket
447      *
448      * @param port the remote port for the socket.
449      *
450      * @throws IllegalArgumentException
451      *         if the address is null, or the port is out of range.
452      *
453      * @throws SecurityException
454      *         if a security manager has been installed and it does
455      *         not permit access to the given remote address
456      *
457      * @see #disconnect
458      */
connect(InetAddress address, int port)459     public void connect(InetAddress address, int port) {
460         try {
461             connectInternal(address, port);
462         } catch (SocketException se) {
463             throw new Error("connect failed", se);
464         }
465     }
466 
467     /**
468      * Connects this socket to a remote socket address (IP address + port number).
469      *
470      * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method
471      * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)}
472      * with the given socket addresses IP address and port number.
473      *
474      * @param   addr    The remote address.
475      *
476      * @throws  SocketException
477      *          if the connect fails
478      *
479      * @throws IllegalArgumentException
480      *         if {@code addr} is {@code null}, or {@code addr} is a SocketAddress
481      *         subclass not supported by this socket
482      *
483      * @throws SecurityException
484      *         if a security manager has been installed and it does
485      *         not permit access to the given remote address
486      *
487      * @since 1.4
488      */
connect(SocketAddress addr)489     public void connect(SocketAddress addr) throws SocketException {
490         if (addr == null)
491             throw new IllegalArgumentException("Address can't be null");
492         if (!(addr instanceof InetSocketAddress))
493             throw new IllegalArgumentException("Unsupported address type");
494         InetSocketAddress epoint = (InetSocketAddress) addr;
495         if (epoint.isUnresolved())
496             throw new SocketException("Unresolved address");
497         connectInternal(epoint.getAddress(), epoint.getPort());
498     }
499 
500     /**
501      * Disconnects the socket. If the socket is closed or not connected,
502      * then this method has no effect.
503      *
504      * @see #connect
505      */
disconnect()506     public void disconnect() {
507         synchronized (this) {
508             if (isClosed())
509                 return;
510             if (connectState == ST_CONNECTED) {
511                 impl.disconnect ();
512             }
513             connectedAddress = null;
514             connectedPort = -1;
515             connectState = ST_NOT_CONNECTED;
516             explicitFilter = false;
517         }
518     }
519 
520     /**
521      * Returns the binding state of the socket.
522      * <p>
523      * If the socket was bound prior to being {@link #close closed},
524      * then this method will continue to return {@code true}
525      * after the socket is closed.
526      *
527      * @return true if the socket successfully bound to an address
528      * @since 1.4
529      */
isBound()530     public boolean isBound() {
531         return bound;
532     }
533 
534     /**
535      * Returns the connection state of the socket.
536      * <p>
537      * If the socket was connected prior to being {@link #close closed},
538      * then this method will continue to return {@code true}
539      * after the socket is closed.
540      *
541      * @return true if the socket successfully connected to a server
542      * @since 1.4
543      */
isConnected()544     public boolean isConnected() {
545         return connectState != ST_NOT_CONNECTED;
546     }
547 
548     /**
549      * Returns the address to which this socket is connected. Returns
550      * {@code null} if the socket is not connected.
551      * <p>
552      * If the socket was connected prior to being {@link #close closed},
553      * then this method will continue to return the connected address
554      * after the socket is closed.
555      *
556      * @return the address to which this socket is connected.
557      */
getInetAddress()558     public InetAddress getInetAddress() {
559         return connectedAddress;
560     }
561 
562     /**
563      * Returns the port number to which this socket is connected.
564      * Returns {@code -1} if the socket is not connected.
565      * <p>
566      * If the socket was connected prior to being {@link #close closed},
567      * then this method will continue to return the connected port number
568      * after the socket is closed.
569      *
570      * @return the port number to which this socket is connected.
571      */
getPort()572     public int getPort() {
573         return connectedPort;
574     }
575 
576     /**
577      * Returns the address of the endpoint this socket is connected to, or
578      * {@code null} if it is unconnected.
579      * <p>
580      * If the socket was connected prior to being {@link #close closed},
581      * then this method will continue to return the connected address
582      * after the socket is closed.
583      *
584      * @return a {@code SocketAddress} representing the remote
585      *         endpoint of this socket, or {@code null} if it is
586      *         not connected yet.
587      * @see #getInetAddress()
588      * @see #getPort()
589      * @see #connect(SocketAddress)
590      * @since 1.4
591      */
getRemoteSocketAddress()592     public SocketAddress getRemoteSocketAddress() {
593         if (!isConnected())
594             return null;
595         return new InetSocketAddress(getInetAddress(), getPort());
596     }
597 
598     /**
599      * Returns the address of the endpoint this socket is bound to.
600      *
601      * @return a {@code SocketAddress} representing the local endpoint of this
602      *         socket, or {@code null} if it is closed or not bound yet.
603      * @see #getLocalAddress()
604      * @see #getLocalPort()
605      * @see #bind(SocketAddress)
606      * @since 1.4
607      */
608 
getLocalSocketAddress()609     public SocketAddress getLocalSocketAddress() {
610         if (isClosed())
611             return null;
612         if (!isBound())
613             return null;
614         return new InetSocketAddress(getLocalAddress(), getLocalPort());
615     }
616 
617     /**
618      * Sends a datagram packet from this socket. The
619      * {@code DatagramPacket} includes information indicating the
620      * data to be sent, its length, the IP address of the remote host,
621      * and the port number on the remote host.
622      *
623      * <p>If there is a security manager, and the socket is not currently
624      * connected to a remote address, this method first performs some
625      * security checks. First, if {@code p.getAddress().isMulticastAddress()}
626      * is true, this method calls the
627      * security manager's {@code checkMulticast} method
628      * with {@code p.getAddress()} as its argument.
629      * If the evaluation of that expression is false,
630      * this method instead calls the security manager's
631      * {@code checkConnect} method with arguments
632      * {@code p.getAddress().getHostAddress()} and
633      * {@code p.getPort()}. Each call to a security manager method
634      * could result in a SecurityException if the operation is not allowed.
635      *
636      * @param      p   the {@code DatagramPacket} to be sent.
637      *
638      * @exception  IOException  if an I/O error occurs.
639      * @exception  SecurityException  if a security manager exists and its
640      *             {@code checkMulticast} or {@code checkConnect}
641      *             method doesn't allow the send.
642      * @exception  PortUnreachableException may be thrown if the socket is connected
643      *             to a currently unreachable destination. Note, there is no
644      *             guarantee that the exception will be thrown.
645      * @exception  java.nio.channels.IllegalBlockingModeException
646      *             if this socket has an associated channel,
647      *             and the channel is in non-blocking mode.
648      * @exception  IllegalArgumentException if the socket is connected,
649      *             and connected address and packet address differ.
650      *
651      * @see        java.net.DatagramPacket
652      * @see        SecurityManager#checkMulticast(InetAddress)
653      * @see        SecurityManager#checkConnect
654      * @revised 1.4
655      * @spec JSR-51
656      */
send(DatagramPacket p)657     public void send(DatagramPacket p) throws IOException  {
658         InetAddress packetAddress = null;
659         synchronized (p) {
660             if (isClosed())
661                 throw new SocketException("Socket is closed");
662             checkAddress (p.getAddress(), "send");
663             if (connectState == ST_NOT_CONNECTED) {
664                 // check the address is ok with the security manager on every send.
665                 SecurityManager security = System.getSecurityManager();
666 
667                 // The reason you want to synchronize on datagram packet
668                 // is because you don't want an applet to change the address
669                 // while you are trying to send the packet for example
670                 // after the security check but before the send.
671                 if (security != null) {
672                     if (p.getAddress().isMulticastAddress()) {
673                         security.checkMulticast(p.getAddress());
674                     } else {
675                         security.checkConnect(p.getAddress().getHostAddress(),
676                                               p.getPort());
677                     }
678                 }
679             } else {
680                 // we're connected
681                 packetAddress = p.getAddress();
682                 if (packetAddress == null) {
683                     p.setAddress(connectedAddress);
684                     p.setPort(connectedPort);
685                 } else if ((!packetAddress.equals(connectedAddress)) ||
686                            p.getPort() != connectedPort) {
687                     throw new IllegalArgumentException("connected address " +
688                                                        "and packet address" +
689                                                        " differ");
690                 }
691             }
692             // Check whether the socket is bound
693             if (!isBound())
694                 bind(new InetSocketAddress(0));
695             // call the  method to send
696             getImpl().send(p);
697         }
698     }
699 
700     /**
701      * Receives a datagram packet from this socket. When this method
702      * returns, the {@code DatagramPacket}'s buffer is filled with
703      * the data received. The datagram packet also contains the sender's
704      * IP address, and the port number on the sender's machine.
705      * <p>
706      * This method blocks until a datagram is received. The
707      * {@code length} field of the datagram packet object contains
708      * the length of the received message. If the message is longer than
709      * the packet's length, the message is truncated.
710      * <p>
711      * If there is a security manager, a packet cannot be received if the
712      * security manager's {@code checkAccept} method
713      * does not allow it.
714      *
715      * @param      p   the {@code DatagramPacket} into which to place
716      *                 the incoming data.
717      * @exception  IOException  if an I/O error occurs.
718      * @exception  SocketTimeoutException  if setSoTimeout was previously called
719      *                 and the timeout has expired.
720      * @exception  PortUnreachableException may be thrown if the socket is connected
721      *             to a currently unreachable destination. Note, there is no guarantee that the
722      *             exception will be thrown.
723      * @exception  java.nio.channels.IllegalBlockingModeException
724      *             if this socket has an associated channel,
725      *             and the channel is in non-blocking mode.
726      * @see        java.net.DatagramPacket
727      * @see        java.net.DatagramSocket
728      * @revised 1.4
729      * @spec JSR-51
730      */
receive(DatagramPacket p)731     public synchronized void receive(DatagramPacket p) throws IOException {
732         synchronized (p) {
733             if (!isBound())
734                 bind(new InetSocketAddress(0));
735             if (connectState == ST_NOT_CONNECTED) {
736                 // check the address is ok with the security manager before every recv.
737                 SecurityManager security = System.getSecurityManager();
738                 if (security != null) {
739                     while(true) {
740                         String peekAd = null;
741                         int peekPort = 0;
742                         // peek at the packet to see who it is from.
743                         if (!oldImpl) {
744                             // We can use the new peekData() API
745                             DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
746                             peekPort = getImpl().peekData(peekPacket);
747                             peekAd = peekPacket.getAddress().getHostAddress();
748                         } else {
749                             InetAddress adr = new InetAddress();
750                             peekPort = getImpl().peek(adr);
751                             peekAd = adr.getHostAddress();
752                         }
753                         try {
754                             security.checkAccept(peekAd, peekPort);
755                             // security check succeeded - so now break
756                             // and recv the packet.
757                             break;
758                         } catch (SecurityException se) {
759                             // Throw away the offending packet by consuming
760                             // it in a tmp buffer.
761                             DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
762                             getImpl().receive(tmp);
763 
764                             // silently discard the offending packet
765                             // and continue: unknown/malicious
766                             // entities on nets should not make
767                             // runtime throw security exception and
768                             // disrupt the applet by sending random
769                             // datagram packets.
770                             continue;
771                         }
772                     } // end of while
773                 }
774             }
775             DatagramPacket tmp = null;
776             if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
777                 // We have to do the filtering the old fashioned way since
778                 // the native impl doesn't support connect or the connect
779                 // via the impl failed, or .. "explicitFilter" may be set when
780                 // a socket is connected via the impl, for a period of time
781                 // when packets from other sources might be queued on socket.
782                 boolean stop = false;
783                 while (!stop) {
784                     InetAddress peekAddress = null;
785                     int peekPort = -1;
786                     // peek at the packet to see who it is from.
787                     if (!oldImpl) {
788                         // We can use the new peekData() API
789                         DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
790                         peekPort = getImpl().peekData(peekPacket);
791                         peekAddress = peekPacket.getAddress();
792                     } else {
793                         // this api only works for IPv4
794                         peekAddress = new InetAddress();
795                         peekPort = getImpl().peek(peekAddress);
796                     }
797                     if ((!connectedAddress.equals(peekAddress)) ||
798                         (connectedPort != peekPort)) {
799                         // throw the packet away and silently continue
800                         tmp = new DatagramPacket(
801                                                 new byte[1024], 1024);
802                         getImpl().receive(tmp);
803                         if (explicitFilter) {
804                             if (checkFiltering(tmp)) {
805                                 stop = true;
806                             }
807                         }
808                     } else {
809                         stop = true;
810                     }
811                 }
812             }
813             // If the security check succeeds, or the datagram is
814             // connected then receive the packet
815             getImpl().receive(p);
816             if (explicitFilter && tmp == null) {
817                 // packet was not filtered, account for it here
818                 checkFiltering(p);
819             }
820         }
821     }
822 
checkFiltering(DatagramPacket p)823     private boolean checkFiltering(DatagramPacket p) throws SocketException {
824         bytesLeftToFilter -= p.getLength();
825         if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) {
826             explicitFilter = false;
827             return true;
828         }
829         return false;
830     }
831 
832     /**
833      * Gets the local address to which the socket is bound.
834      *
835      * <p>If there is a security manager, its
836      * {@code checkConnect} method is first called
837      * with the host address and {@code -1}
838      * as its arguments to see if the operation is allowed.
839      *
840      * @see SecurityManager#checkConnect
841      * @return  the local address to which the socket is bound,
842      *          {@code null} if the socket is closed, or
843      *          an {@code InetAddress} representing
844      *          {@link InetAddress#isAnyLocalAddress wildcard}
845      *          address if either the socket is not bound, or
846      *          the security manager {@code checkConnect}
847      *          method does not allow the operation
848      * @since   1.1
849      */
getLocalAddress()850     public InetAddress getLocalAddress() {
851         if (isClosed())
852             return null;
853         InetAddress in = null;
854         try {
855             in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
856             if (in.isAnyLocalAddress()) {
857                 in = InetAddress.anyLocalAddress();
858             }
859             SecurityManager s = System.getSecurityManager();
860             if (s != null) {
861                 s.checkConnect(in.getHostAddress(), -1);
862             }
863         } catch (Exception e) {
864             in = InetAddress.anyLocalAddress(); // "0.0.0.0"
865         }
866         return in;
867     }
868 
869     /**
870      * Returns the port number on the local host to which this socket
871      * is bound.
872      *
873      * @return  the port number on the local host to which this socket is bound,
874                 {@code -1} if the socket is closed, or
875                 {@code 0} if it is not bound yet.
876      */
getLocalPort()877     public int getLocalPort() {
878         if (isClosed())
879             return -1;
880         try {
881             return getImpl().getLocalPort();
882         } catch (Exception e) {
883             return 0;
884         }
885     }
886 
887     /** Enable/disable SO_TIMEOUT with the specified timeout, in
888      *  milliseconds. With this option set to a non-zero timeout,
889      *  a call to receive() for this DatagramSocket
890      *  will block for only this amount of time.  If the timeout expires,
891      *  a <B>java.net.SocketTimeoutException</B> is raised, though the
892      *  DatagramSocket is still valid.  The option <B>must</B> be enabled
893      *  prior to entering the blocking operation to have effect.  The
894      *  timeout must be {@code > 0}.
895      *  A timeout of zero is interpreted as an infinite timeout.
896      *
897      * @param timeout the specified timeout in milliseconds.
898      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
899      * @since   1.1
900      * @see #getSoTimeout()
901      */
setSoTimeout(int timeout)902     public synchronized void setSoTimeout(int timeout) throws SocketException {
903         if (isClosed())
904             throw new SocketException("Socket is closed");
905         getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
906     }
907 
908     /**
909      * Retrieve setting for SO_TIMEOUT.  0 returns implies that the
910      * option is disabled (i.e., timeout of infinity).
911      *
912      * @return the setting for SO_TIMEOUT
913      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
914      * @since   1.1
915      * @see #setSoTimeout(int)
916      */
getSoTimeout()917     public synchronized int getSoTimeout() throws SocketException {
918         if (isClosed())
919             throw new SocketException("Socket is closed");
920         if (getImpl() == null)
921             return 0;
922         Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
923         /* extra type safety */
924         if (o instanceof Integer) {
925             return ((Integer) o).intValue();
926         } else {
927             return 0;
928         }
929     }
930 
931     /**
932      * Sets the SO_SNDBUF option to the specified value for this
933      * {@code DatagramSocket}. The SO_SNDBUF option is used by the
934      * network implementation as a hint to size the underlying
935      * network I/O buffers. The SO_SNDBUF setting may also be used
936      * by the network implementation to determine the maximum size
937      * of the packet that can be sent on this socket.
938      * <p>
939      * As SO_SNDBUF is a hint, applications that want to verify
940      * what size the buffer is should call {@link #getSendBufferSize()}.
941      * <p>
942      * Increasing the buffer size may allow multiple outgoing packets
943      * to be queued by the network implementation when the send rate
944      * is high.
945      * <p>
946      * Note: If {@link #send(DatagramPacket)} is used to send a
947      * {@code DatagramPacket} that is larger than the setting
948      * of SO_SNDBUF then it is implementation specific if the
949      * packet is sent or discarded.
950      *
951      * @param size the size to which to set the send buffer
952      * size. This value must be greater than 0.
953      *
954      * @exception SocketException if there is an error
955      * in the underlying protocol, such as an UDP error.
956      * @exception IllegalArgumentException if the value is 0 or is
957      * negative.
958      * @see #getSendBufferSize()
959      */
setSendBufferSize(int size)960     public synchronized void setSendBufferSize(int size)
961     throws SocketException{
962         if (!(size > 0)) {
963             throw new IllegalArgumentException("negative send size");
964         }
965         if (isClosed())
966             throw new SocketException("Socket is closed");
967         getImpl().setOption(SocketOptions.SO_SNDBUF, size);
968     }
969 
970     /**
971      * Get value of the SO_SNDBUF option for this {@code DatagramSocket}, that is the
972      * buffer size used by the platform for output on this {@code DatagramSocket}.
973      *
974      * @return the value of the SO_SNDBUF option for this {@code DatagramSocket}
975      * @exception SocketException if there is an error in
976      * the underlying protocol, such as an UDP error.
977      * @see #setSendBufferSize
978      */
getSendBufferSize()979     public synchronized int getSendBufferSize() throws SocketException {
980         if (isClosed())
981             throw new SocketException("Socket is closed");
982         int result = 0;
983         Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
984         if (o instanceof Integer) {
985             result = ((Integer)o).intValue();
986         }
987         return result;
988     }
989 
990     /**
991      * Sets the SO_RCVBUF option to the specified value for this
992      * {@code DatagramSocket}. The SO_RCVBUF option is used by
993      * the network implementation as a hint to size the underlying
994      * network I/O buffers. The SO_RCVBUF setting may also be used
995      * by the network implementation to determine the maximum size
996      * of the packet that can be received on this socket.
997      * <p>
998      * Because SO_RCVBUF is a hint, applications that want to
999      * verify what size the buffers were set to should call
1000      * {@link #getReceiveBufferSize()}.
1001      * <p>
1002      * Increasing SO_RCVBUF may allow the network implementation
1003      * to buffer multiple packets when packets arrive faster than
1004      * are being received using {@link #receive(DatagramPacket)}.
1005      * <p>
1006      * Note: It is implementation specific if a packet larger
1007      * than SO_RCVBUF can be received.
1008      *
1009      * @param size the size to which to set the receive buffer
1010      * size. This value must be greater than 0.
1011      *
1012      * @exception SocketException if there is an error in
1013      * the underlying protocol, such as an UDP error.
1014      * @exception IllegalArgumentException if the value is 0 or is
1015      * negative.
1016      * @see #getReceiveBufferSize()
1017      */
setReceiveBufferSize(int size)1018     public synchronized void setReceiveBufferSize(int size)
1019     throws SocketException{
1020         if (size <= 0) {
1021             throw new IllegalArgumentException("invalid receive size");
1022         }
1023         if (isClosed())
1024             throw new SocketException("Socket is closed");
1025         getImpl().setOption(SocketOptions.SO_RCVBUF, size);
1026     }
1027 
1028     /**
1029      * Get value of the SO_RCVBUF option for this {@code DatagramSocket}, that is the
1030      * buffer size used by the platform for input on this {@code DatagramSocket}.
1031      *
1032      * @return the value of the SO_RCVBUF option for this {@code DatagramSocket}
1033      * @exception SocketException if there is an error in the underlying protocol, such as an UDP error.
1034      * @see #setReceiveBufferSize(int)
1035      */
getReceiveBufferSize()1036     public synchronized int getReceiveBufferSize()
1037     throws SocketException{
1038         if (isClosed())
1039             throw new SocketException("Socket is closed");
1040         int result = 0;
1041         Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
1042         if (o instanceof Integer) {
1043             result = ((Integer)o).intValue();
1044         }
1045         return result;
1046     }
1047 
1048     /**
1049      * Enable/disable the SO_REUSEADDR socket option.
1050      * <p>
1051      * For UDP sockets it may be necessary to bind more than one
1052      * socket to the same socket address. This is typically for the
1053      * purpose of receiving multicast packets
1054      * (See {@link java.net.MulticastSocket}). The
1055      * {@code SO_REUSEADDR} socket option allows multiple
1056      * sockets to be bound to the same socket address if the
1057      * {@code SO_REUSEADDR} socket option is enabled prior
1058      * to binding the socket using {@link #bind(SocketAddress)}.
1059      * <p>
1060      * Note: This functionality is not supported by all existing platforms,
1061      * so it is implementation specific whether this option will be ignored
1062      * or not. However, if it is not supported then
1063      * {@link #getReuseAddress()} will always return {@code false}.
1064      * <p>
1065      * When a {@code DatagramSocket} is created the initial setting
1066      * of {@code SO_REUSEADDR} is disabled.
1067      * <p>
1068      * The behaviour when {@code SO_REUSEADDR} is enabled or
1069      * disabled after a socket is bound (See {@link #isBound()})
1070      * is not defined.
1071      *
1072      * @param on  whether to enable or disable the
1073      * @exception SocketException if an error occurs enabling or
1074      *            disabling the {@code SO_REUSEADDR} socket option,
1075      *            or the socket is closed.
1076      * @since 1.4
1077      * @see #getReuseAddress()
1078      * @see #bind(SocketAddress)
1079      * @see #isBound()
1080      * @see #isClosed()
1081      */
setReuseAddress(boolean on)1082     public synchronized void setReuseAddress(boolean on) throws SocketException {
1083         if (isClosed())
1084             throw new SocketException("Socket is closed");
1085         // Integer instead of Boolean for compatibility with older DatagramSocketImpl
1086         if (oldImpl)
1087             getImpl().setOption(SocketOptions.SO_REUSEADDR, on?-1:0);
1088         else
1089             getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
1090     }
1091 
1092     /**
1093      * Tests if SO_REUSEADDR is enabled.
1094      *
1095      * @return a {@code boolean} indicating whether or not SO_REUSEADDR is enabled.
1096      * @exception SocketException if there is an error
1097      * in the underlying protocol, such as an UDP error.
1098      * @since   1.4
1099      * @see #setReuseAddress(boolean)
1100      */
getReuseAddress()1101     public synchronized boolean getReuseAddress() throws SocketException {
1102         if (isClosed())
1103             throw new SocketException("Socket is closed");
1104         Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1105         return ((Boolean)o).booleanValue();
1106     }
1107 
1108     /**
1109      * Enable/disable SO_BROADCAST.
1110      *
1111      * <p> Some operating systems may require that the Java virtual machine be
1112      * started with implementation specific privileges to enable this option or
1113      * send broadcast datagrams.
1114      *
1115      * @param  on
1116      *         whether or not to have broadcast turned on.
1117      *
1118      * @throws  SocketException
1119      *          if there is an error in the underlying protocol, such as an UDP
1120      *          error.
1121      *
1122      * @since 1.4
1123      * @see #getBroadcast()
1124      */
setBroadcast(boolean on)1125     public synchronized void setBroadcast(boolean on) throws SocketException {
1126         if (isClosed())
1127             throw new SocketException("Socket is closed");
1128         getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on));
1129     }
1130 
1131     /**
1132      * Tests if SO_BROADCAST is enabled.
1133      * @return a {@code boolean} indicating whether or not SO_BROADCAST is enabled.
1134      * @exception SocketException if there is an error
1135      * in the underlying protocol, such as an UDP error.
1136      * @since 1.4
1137      * @see #setBroadcast(boolean)
1138      */
getBroadcast()1139     public synchronized boolean getBroadcast() throws SocketException {
1140         if (isClosed())
1141             throw new SocketException("Socket is closed");
1142         return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue();
1143     }
1144 
1145     /**
1146      * Sets traffic class or type-of-service octet in the IP
1147      * datagram header for datagrams sent from this DatagramSocket.
1148      * As the underlying network implementation may ignore this
1149      * value applications should consider it a hint.
1150      *
1151      * <P> The tc <B>must</B> be in the range {@code 0 <= tc <=
1152      * 255} or an IllegalArgumentException will be thrown.
1153      * <p>Notes:
1154      * <p>For Internet Protocol v4 the value consists of an
1155      * {@code integer}, the least significant 8 bits of which
1156      * represent the value of the TOS octet in IP packets sent by
1157      * the socket.
1158      * RFC 1349 defines the TOS values as follows:
1159      *
1160      * <UL>
1161      * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1162      * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1163      * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1164      * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1165      * </UL>
1166      * The last low order bit is always ignored as this
1167      * corresponds to the MBZ (must be zero) bit.
1168      * <p>
1169      * Setting bits in the precedence field may result in a
1170      * SocketException indicating that the operation is not
1171      * permitted.
1172      * <p>
1173      * for Internet Protocol v6 {@code tc} is the value that
1174      * would be placed into the sin6_flowinfo field of the IP header.
1175      *
1176      * @param tc        an {@code int} value for the bitset.
1177      * @throws SocketException if there is an error setting the
1178      * traffic class or type-of-service
1179      * @since 1.4
1180      * @see #getTrafficClass
1181      */
setTrafficClass(int tc)1182     public synchronized void setTrafficClass(int tc) throws SocketException {
1183         if (tc < 0 || tc > 255)
1184             throw new IllegalArgumentException("tc is not in range 0 -- 255");
1185 
1186         if (isClosed())
1187             throw new SocketException("Socket is closed");
1188         try {
1189             getImpl().setOption(SocketOptions.IP_TOS, tc);
1190         } catch (SocketException se) {
1191             // not supported if socket already connected
1192             // Solaris returns error in such cases
1193             if(!isConnected())
1194                 throw se;
1195         }
1196     }
1197 
1198     /**
1199      * Gets traffic class or type-of-service in the IP datagram
1200      * header for packets sent from this DatagramSocket.
1201      * <p>
1202      * As the underlying network implementation may ignore the
1203      * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1204      * this method may return a different value than was previously
1205      * set using the {@link #setTrafficClass(int)} method on this
1206      * DatagramSocket.
1207      *
1208      * @return the traffic class or type-of-service already set
1209      * @throws SocketException if there is an error obtaining the
1210      * traffic class or type-of-service value.
1211      * @since 1.4
1212      * @see #setTrafficClass(int)
1213      */
getTrafficClass()1214     public synchronized int getTrafficClass() throws SocketException {
1215         if (isClosed())
1216             throw new SocketException("Socket is closed");
1217         return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue();
1218     }
1219 
1220     /**
1221      * Closes this datagram socket.
1222      * <p>
1223      * Any thread currently blocked in {@link #receive} upon this socket
1224      * will throw a {@link SocketException}.
1225      *
1226      * <p> If this socket has an associated channel then the channel is closed
1227      * as well.
1228      *
1229      * @revised 1.4
1230      * @spec JSR-51
1231      */
close()1232     public void close() {
1233         synchronized(closeLock) {
1234             if (isClosed())
1235                 return;
1236             impl.close();
1237             closed = true;
1238         }
1239     }
1240 
1241     /**
1242      * Returns whether the socket is closed or not.
1243      *
1244      * @return true if the socket has been closed
1245      * @since 1.4
1246      */
isClosed()1247     public boolean isClosed() {
1248         synchronized(closeLock) {
1249             return closed;
1250         }
1251     }
1252 
1253     /**
1254      * Returns the unique {@link java.nio.channels.DatagramChannel} object
1255      * associated with this datagram socket, if any.
1256      *
1257      * <p> A datagram socket will have a channel if, and only if, the channel
1258      * itself was created via the {@link java.nio.channels.DatagramChannel#open
1259      * DatagramChannel.open} method.
1260      *
1261      * @return  the datagram channel associated with this datagram socket,
1262      *          or {@code null} if this socket was not created for a channel
1263      *
1264      * @since 1.4
1265      * @spec JSR-51
1266      */
getChannel()1267     public DatagramChannel getChannel() {
1268         return null;
1269     }
1270 
1271     /**
1272      * User defined factory for all datagram sockets.
1273      */
1274     static DatagramSocketImplFactory factory;
1275 
1276     /**
1277      * Sets the datagram socket implementation factory for the
1278      * application. The factory can be specified only once.
1279      * <p>
1280      * When an application creates a new datagram socket, the socket
1281      * implementation factory's {@code createDatagramSocketImpl} method is
1282      * called to create the actual datagram socket implementation.
1283      * <p>
1284      * Passing {@code null} to the method is a no-op unless the factory
1285      * was already set.
1286      *
1287      * <p>If there is a security manager, this method first calls
1288      * the security manager's {@code checkSetFactory} method
1289      * to ensure the operation is allowed.
1290      * This could result in a SecurityException.
1291      *
1292      * @param      fac   the desired factory.
1293      * @exception  IOException  if an I/O error occurs when setting the
1294      *              datagram socket factory.
1295      * @exception  SocketException  if the factory is already defined.
1296      * @exception  SecurityException  if a security manager exists and its
1297      *             {@code checkSetFactory} method doesn't allow the operation.
1298      * @see       java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
1299      * @see       SecurityManager#checkSetFactory
1300      * @since 1.3
1301      */
1302     public static synchronized void
setDatagramSocketImplFactory(DatagramSocketImplFactory fac)1303     setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
1304        throws IOException
1305     {
1306         if (factory != null) {
1307             throw new SocketException("factory already defined");
1308         }
1309         SecurityManager security = System.getSecurityManager();
1310         if (security != null) {
1311             security.checkSetFactory();
1312         }
1313         factory = fac;
1314     }
1315 
1316     /**
1317      * Sets the value of a socket option.
1318      *
1319      * @param <T> The type of the socket option value
1320      * @param name The socket option
1321      * @param value The value of the socket option. A value of {@code null}
1322      *              may be valid for some options.
1323      *
1324      * @return this DatagramSocket
1325      *
1326      * @throws UnsupportedOperationException if the datagram socket
1327      *         does not support the option.
1328      *
1329      * @throws IllegalArgumentException if the value is not valid for
1330      *         the option.
1331      *
1332      * @throws IOException if an I/O error occurs, or if the socket is closed.
1333      *
1334      * @throws SecurityException if a security manager is set and if the socket
1335      *         option requires a security permission and if the caller does
1336      *         not have the required permission.
1337      *         {@link java.net.StandardSocketOptions StandardSocketOptions}
1338      *         do not require any security permission.
1339      *
1340      * @throws NullPointerException if name is {@code null}
1341      *
1342      * @since 9
1343      */
setOption(SocketOption<T> name, T value)1344     public <T> DatagramSocket setOption(SocketOption<T> name, T value)
1345         throws IOException
1346     {
1347         Objects.requireNonNull(name);
1348         if (isClosed())
1349             throw new SocketException("Socket is closed");
1350         getImpl().setOption(name, value);
1351         return this;
1352     }
1353 
1354     /**
1355      * Returns the value of a socket option.
1356      *
1357      * @param <T> The type of the socket option value
1358      * @param name The socket option
1359      *
1360      * @return The value of the socket option.
1361      *
1362      * @throws UnsupportedOperationException if the datagram socket
1363      *         does not support the option.
1364      *
1365      * @throws IOException if an I/O error occurs, or if the socket is closed.
1366      *
1367      * @throws NullPointerException if name is {@code null}
1368      *
1369      * @throws SecurityException if a security manager is set and if the socket
1370      *         option requires a security permission and if the caller does
1371      *         not have the required permission.
1372      *         {@link java.net.StandardSocketOptions StandardSocketOptions}
1373      *         do not require any security permission.
1374      *
1375      * @since 9
1376      */
getOption(SocketOption<T> name)1377     public <T> T getOption(SocketOption<T> name) throws IOException {
1378         Objects.requireNonNull(name);
1379         if (isClosed())
1380             throw new SocketException("Socket is closed");
1381         return getImpl().getOption(name);
1382     }
1383 
1384     private static Set<SocketOption<?>> options;
1385     private static boolean optionsSet = false;
1386 
1387     /**
1388      * Returns a set of the socket options supported by this socket.
1389      *
1390      * This method will continue to return the set of options even after
1391      * the socket has been closed.
1392      *
1393      * @return A set of the socket options supported by this socket. This set
1394      *        may be empty if the socket's DatagramSocketImpl cannot be created.
1395      *
1396      * @since 9
1397      */
supportedOptions()1398     public Set<SocketOption<?>> supportedOptions() {
1399         synchronized(DatagramSocket.class) {
1400             if (optionsSet) {
1401                 return options;
1402             }
1403             try {
1404                 DatagramSocketImpl impl = getImpl();
1405                 options = Collections.unmodifiableSet(impl.supportedOptions());
1406             } catch (IOException e) {
1407                 options = Collections.emptySet();
1408             }
1409             optionsSet = true;
1410             return options;
1411         }
1412     }
1413 }
1414