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

Save This Page
Home » openjdk-7 » java » net » [javadoc | source]