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