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