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
26package java.net;
27
28import java.io.IOException;
29import java.nio.channels.DatagramChannel;
30import java.security.AccessController;
31import java.security.PrivilegedExceptionAction;
32import java.util.Set;
33import 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 */
68public
69class 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     */
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     */
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     */
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     */
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     */
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     */
300    public DatagramSocket(int port, InetAddress laddr) throws SocketException {
301        this(new InetSocketAddress(laddr, port));
302    }
303
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
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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 the
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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