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

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