gt:         SecurityManager sec = System.getSecurityManager();
context: /*
   * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package java.net;
  
  import java.io.IOException;
  import java.nio.channels.DatagramChannel;
  import java.security.AccessController;
  import java.security.PrivilegedExceptionAction;
  
  /**
   * This class represents a socket for sending and receiving datagram packets.
   *
   * <p>A datagram socket is the sending or receiving point for a packet
   * delivery service. Each packet sent or received on a datagram socket
   * is individually addressed and routed. Multiple packets sent from
   * one machine to another may be routed differently, and may arrive in
   * any order.
   *
   * <p> Where possible, a newly constructed {@code DatagramSocket} has the
   * {@link SocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as
   * to allow the transmission of broadcast datagrams. In order to receive
   * broadcast packets a DatagramSocket should be bound to the wildcard address.
   * In some implementations, broadcast packets may also be received when
   * a DatagramSocket is bound to a more specific address.
   * <p>
   * Example:
   * <code>
   *              DatagramSocket s = new DatagramSocket(null);
   *              s.bind(new InetSocketAddress(8888));
   * </code>
   * Which is equivalent to:
   * <code>
   *              DatagramSocket s = new DatagramSocket(8888);
   * </code>
   * Both cases will create a DatagramSocket able to receive broadcasts on
   * UDP port 8888.
   *
   * @author  Pavani Diwanji
   * @see     java.net.DatagramPacket
   * @see     java.nio.channels.DatagramChannel
   * @since JDK1.0
   */
  public
  class DatagramSocket implements java.io.Closeable {
      /**
       * Various states of this socket.
       */
      private boolean created = false;
      private boolean bound = false;
      private boolean closed = false;
      private Object closeLock = new Object();
  
      /*
       * The implementation of this DatagramSocket.
       */
      DatagramSocketImpl impl;
  
      /**
       * Are we using an older DatagramSocketImpl?
       */
      boolean oldImpl = false;
  
      /*
       * Connection state:
       * ST_NOT_CONNECTED = socket not connected
       * ST_CONNECTED = socket connected
       * ST_CONNECTED_NO_IMPL = socket connected but not at impl level
       */
      static final int ST_NOT_CONNECTED = 0;
      static final int ST_CONNECTED = 1;
      static final int ST_CONNECTED_NO_IMPL = 2;
  
      int connectState = ST_NOT_CONNECTED;
  
      /*
       * Connected address & port
       */
      InetAddress connectedAddress = null;
      int connectedPort = -1;
  
      /**
       * Connects this socket to a remote socket address (IP address + port number).
       * Binds socket if not already bound.
       * <p>
       * @param   address The remote address.
       * @param   port    The remote port
       * @throws  SocketException if binding the socket fails.
       */
      private synchronized void connectInternal(InetAddress address, int port) throws SocketException {
          if (port < 0 || port > 0xFFFF) {
              throw new IllegalArgumentException("connect: " + port);
          }
          if (address == null) {
              throw new IllegalArgumentException("connect: null address");
          }
          checkAddress (address, "connect");
          if (isClosed())
              return;
          SecurityManager security = System.getSecurityManager();
          if (security != null) {
              if (address.isMulticastAddress()) {
                  security.checkMulticast(address);
              } else {
                  security.checkConnect(address.getHostAddress(), port);
                  security.checkAccept(address.getHostAddress(), port);
              }
          }
  
          if (!isBound())
            bind(new InetSocketAddress(0));
  
          // old impls do not support connect/disconnect
          if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
               ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
              connectState = ST_CONNECTED_NO_IMPL;
          } else {
              try {
                  getImpl().connect(address, port);
  
                  // socket is now connected by the impl
                  connectState = ST_CONNECTED;
              } catch (SocketException se) {
  
                  // connection will be emulated by DatagramSocket
                  connectState = ST_CONNECTED_NO_IMPL;
              }
          }
  
          connectedAddress = address;
          connectedPort = port;
      }
  
  
      /**
       * Constructs a datagram socket and binds it to any available port
       * on the local host machine.  The socket will be bound to the
       * {@link InetAddress#isAnyLocalAddress wildcard} address,
       * an IP address chosen by the kernel.
       *
       * <p>If there is a security manager,
       * its <code>checkListen</code> method is first called
       * with 0 as its argument to ensure the operation is allowed.
       * This could result in a SecurityException.
       *
       * @exception  SocketException  if the socket could not be opened,
       *               or the socket could not bind to the specified local port.
       * @exception  SecurityException  if a security manager exists and its
       *             <code>checkListen</code> method doesn't allow the operation.
       *
       * @see SecurityManager#checkListen
       */
      public DatagramSocket() throws SocketException {
          this(new InetSocketAddress(0));
      }
  
      /**
       * Creates an unbound datagram socket with the specified
       * DatagramSocketImpl.
       *
       * @param impl an instance of a <B>DatagramSocketImpl</B>
       *        the subclass wishes to use on the DatagramSocket.
       * @since   1.4
       */
      protected DatagramSocket(DatagramSocketImpl impl) {
          if (impl == null)
              throw new NullPointerException();
          this.impl = impl;
          checkOldImpl();
      }
  
      /**
       * Creates a datagram socket, bound to the specified local
       * socket address.
       * <p>
       * If, if the address is <code>null</code>, creates an unbound socket.
       * <p>
       * <p>If there is a security manager,
       * its <code>checkListen</code> method is first called
       * with the port from the socket address
       * as its argument to ensure the operation is allowed.
       * This could result in a SecurityException.
       *
       * @param bindaddr local socket address to bind, or <code>null</code>
       *                 for an unbound socket.
       *
       * @exception  SocketException  if the socket could not be opened,
       *               or the socket could not bind to the specified local port.
       * @exception  SecurityException  if a security manager exists and its
       *             <code>checkListen</code> method doesn't allow the operation.
       *
       * @see SecurityManager#checkListen
       * @since   1.4
       */
      public DatagramSocket(SocketAddress bindaddr) throws SocketException {
          // create a datagram socket.
          createImpl();
          if (bindaddr != null) {
              try {
                  bind(bindaddr);
              } finally {
                  if (!isBound())
                      close();
              }
          }
      }
  
      /**
       * Constructs a datagram socket and binds it to the specified port
       * on the local host machine.  The socket will be bound to the
       * {@link InetAddress#isAnyLocalAddress wildcard} address,
       * an IP address chosen by the kernel.
       *
       * <p>If there is a security manager,
       * its <code>checkListen</code> method is first called
       * with the <code>port</code> argument
       * as its argument to ensure the operation is allowed.
       * This could result in a SecurityException.
       *
       * @param      port port to use.
       * @exception  SocketException  if the socket could not be opened,
       *               or the socket could not bind to the specified local port.
       * @exception  SecurityException  if a security manager exists and its
       *             <code>checkListen</code> method doesn't allow the operation.
       *
       * @see SecurityManager#checkListen
       */
      public DatagramSocket(int port) throws SocketException {
          this(port, null);
      }
  
      /**
       * Creates a datagram socket, bound to the specified local
       * address.  The local port must be between 0 and 65535 inclusive.
       * If the IP address is 0.0.0.0, the socket will be bound to the
       * {@link InetAddress#isAnyLocalAddress wildcard} address,
       * an IP address chosen by the kernel.
       *
       * <p>If there is a security manager,
       * its <code>checkListen</code> method is first called
       * with the <code>port</code> argument
       * as its argument to ensure the operation is allowed.
       * This could result in a SecurityException.
       *
       * @param port local port to use
       * @param laddr local address to bind
       *
       * @exception  SocketException  if the socket could not be opened,
       *               or the socket could not bind to the specified local port.
       * @exception  SecurityException  if a security manager exists and its
       *             <code>checkListen</code> method doesn't allow the operation.
       *
       * @see SecurityManager#checkListen
       * @since   JDK1.1
       */
      public DatagramSocket(int port, InetAddress laddr) throws SocketException {
          this(new InetSocketAddress(laddr, port));
      }
  
      private void checkOldImpl() {
          if (impl == null)
              return;
          // DatagramSocketImpl.peekdata() is a protected method, therefore we need to use
          // getDeclaredMethod, therefore we need permission to access the member
          try {
              AccessController.doPrivileged(
                  new PrivilegedExceptionAction<Void>() {
                      public Void run() throws NoSuchMethodException {
                          Class<?>[] cl = new Class<?>[1];
                          cl[0] = DatagramPacket.class;
                          impl.getClass().getDeclaredMethod("peekData", cl);
                          return null;
                      }
                  });
          } catch (java.security.PrivilegedActionException e) {
              oldImpl = true;
          }
      }
  
      static Class<?> implClass = null;
  
      void createImpl() throws SocketException {
          if (impl == null) {
              if (factory != null) {
                  impl = factory.createDatagramSocketImpl();
                  checkOldImpl();
              } else {
                  boolean isMulticast = (this instanceof MulticastSocket) ? true : false;
                  impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast);
  
                  checkOldImpl();
              }
          }
          // creates a udp socket
          impl.create();
          created = true;
      }
  
      /**
       * Get the <code>DatagramSocketImpl</code> attached to this socket,
       * creating it if necessary.
       *
       * @return  the <code>DatagramSocketImpl</code> attached to that
       *          DatagramSocket
       * @throws SocketException if creation fails.
       * @since 1.4
       */
      DatagramSocketImpl getImpl() throws SocketException {
          if (!created)
              createImpl();
          return impl;
      }
  
      /**
       * Binds this DatagramSocket to a specific address & port.
       * <p>
       * If the address is <code>null</code>, then the system will pick up
       * an ephemeral port and a valid local address to bind the socket.
       *<p>
       * @param   addr The address & port to bind to.
       * @throws  SocketException if any error happens during the bind, or if the
       *          socket is already bound.
       * @throws  SecurityException  if a security manager exists and its
       *             <code>checkListen</code> method doesn't allow the operation.
       * @throws IllegalArgumentException if addr is a SocketAddress subclass
       *         not supported by this socket.
       * @since 1.4
       */
      public synchronized void bind(SocketAddress addr) throws SocketException {
          if (isClosed())
              throw new SocketException("Socket is closed");
          if (isBound())
              throw new SocketException("already bound");
          if (addr == null)
              addr = new InetSocketAddress(0);
          if (!(addr instanceof InetSocketAddress))
              throw new IllegalArgumentException("Unsupported address type!");
          InetSocketAddress epoint = (InetSocketAddress) addr;
          if (epoint.isUnresolved())
              throw new SocketException("Unresolved address");
          InetAddress iaddr = epoint.getAddress();
          int port = epoint.getPort();
          checkAddress(iaddr, "bind");
  