home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / DatagramSocket.java < prev    next >
Text File  |  1998-09-22  |  10KB  |  290 lines

  1. /*
  2.  * @(#)DatagramSocket.java    1.26 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.net;
  16.  
  17. import java.io.FileDescriptor;
  18. import java.io.IOException;
  19. import java.io.InterruptedIOException;
  20.  
  21. /**
  22.  * This class represents a socket for sending and receiving datagram packets.
  23.  * <p>
  24.  * A datagram socket is the sending or receiving point for a 
  25.  * connectionless packet delivery service. Each packet sent or 
  26.  * received on a datagram socket is individually addressed and 
  27.  * routed. Multiple packets sent from one machine to another may be 
  28.  * routed differently, and may arrive in any order. 
  29.  *
  30.  * @author  Pavani Diwanji
  31.  * @version 1.26, 07/01/98
  32.  * @see     java.net.DatagramPacket
  33.  * @since   JDK1.0
  34. */
  35. public
  36. class DatagramSocket {
  37.     /*
  38.      * The implementation of this DatagramSocket.
  39.      */
  40.     DatagramSocketImpl impl;
  41.  
  42.     /*
  43.      * The Class of DatagramSocketImpl we use for this runtime.  
  44.      */
  45.  
  46.     static Class implClass;
  47.  
  48.     static {
  49.     String prefix = "";
  50.     try {
  51.  
  52.         prefix = System.getProperty("impl.prefix", "Plain");
  53.  
  54.         implClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
  55.     } catch (Exception e) {
  56.         System.err.println("Can't find class: java.net." + prefix +
  57.                    "DatagramSocketImpl: check impl.prefix property");
  58.     }
  59.  
  60.     if (implClass == null) {
  61.         try {
  62.         implClass = Class.forName("java.net.PlainDatagramSocketImpl");
  63.         } catch (Exception e) {
  64.         throw new Error("System property impl.prefix incorrect");
  65.         }
  66.     }
  67.     }
  68.  
  69.     /**
  70.      * Constructs a datagram socket and binds it to any available port 
  71.      * on the local host machine. 
  72.      *
  73.      * @exception  SocketException  if the socket could not be opened,
  74.      *               or the socket could not bind to the specified local port.
  75.      * @since      JDK1.0
  76.      */
  77.     public DatagramSocket() throws SocketException {
  78.     // create a datagram socket.
  79.     create(0, null);
  80.     }
  81.  
  82.     /**
  83.      * Constructs a datagram socket and binds it to the specified port 
  84.      * on the local host machine. 
  85.      *
  86.      * @param      local   port to use.
  87.      * @exception  SocketException  if the socket could not be opened,
  88.      *               or the socket could not bind to the specified local port.
  89.      * @since      JDK1.0
  90.      */
  91.     public DatagramSocket(int port) throws SocketException {
  92.     this(port, null);
  93.     }
  94.  
  95.     /**
  96.      * Creates a datagram socket, bound to the specified local
  97.      * address.  The local port must be between 0 and 65535 inclusive.
  98.      * @param port local port to use
  99.      * @param laddr local address to bind
  100.      * @since   JDK1.1
  101.      */
  102.     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
  103.     if (port < 0 || port > 0xFFFF)
  104.         throw new IllegalArgumentException("Port out of range:"+port);
  105.  
  106.     create(port, laddr);
  107.     }
  108.  
  109.     /* do the work of creating a vanilla datagramsocket.  It is
  110.      * important that the signature of this method not change,
  111.      * even though it is package-private since it is overridden by
  112.      * MulticastSocket, which must set SO_REUSEADDR.
  113.      */
  114.     void create(int port, InetAddress laddr) throws SocketException {
  115.     SecurityManager sec = System.getSecurityManager();
  116.     if (sec != null) {
  117.         sec.checkListen(port);
  118.     }
  119.     try {
  120.         impl = (DatagramSocketImpl) implClass.newInstance();
  121.     } catch (Exception e) {
  122.         throw new SocketException("can't instantiate DatagramSocketImpl");
  123.     }
  124.     // creates a udp socket
  125.     impl.create();
  126.     // binds the udp socket to desired port + address
  127.     if (laddr == null) {
  128.         laddr = InetAddress.anyLocalAddress;
  129.     }
  130.     impl.bind(port, laddr);
  131.     }
  132.  
  133.     /**
  134.      * Sends a datagram packet from this socket. The 
  135.      * <code>DatagramPacket</code> includes information indicating the 
  136.      * data to be sent, its length, the IP address of the remote host, 
  137.      * and the port number on the remote host. 
  138.      *
  139.      * @param      p   the <code>DatagramPacket</code> to be sent.
  140.      * @exception  IOException  if an I/O error occurs.
  141.      * @see        java.net.DatagramPacket
  142.      * @since      JDK1.0
  143.      */
  144.     public void send(DatagramPacket p) throws IOException  {
  145.  
  146.     // check the address is ok wiht the security manager on every send.
  147.     SecurityManager security = System.getSecurityManager();
  148.  
  149.     // The reason you want to synchronize on datagram packet
  150.     // is because you dont want an applet to change the address 
  151.     // while you are trying to send the packet for example 
  152.     // after the security check but before the send.
  153.     synchronized (p) {
  154.         if (security != null) {
  155.         if (p.getAddress().isMulticastAddress()) {
  156.             security.checkMulticast(p.getAddress());
  157.         } else {
  158.             security.checkConnect(p.getAddress().getHostAddress(), 
  159.                       p.getPort());
  160.         }
  161.         }
  162.             // call the  method to send
  163.             impl.send(p);
  164.         }
  165.     }
  166.  
  167.     /**
  168.      * Receives a datagram packet from this socket. When this method 
  169.      * returns, the <code>DatagramPacket</code>'s buffer is filled with 
  170.      * the data received. The datagram packet also contains the sender's 
  171.      * IP address, and the port number on the sender's machine. 
  172.      * <p>
  173.      * This method blocks until a datagram is received. The 
  174.      * <code>length</code> field of the datagram packet object contains 
  175.      * the length of the received message. If the message is longer than 
  176.      * the buffer length, the message is truncated. 
  177.      *
  178.      * @param      p   the <code>DatagramPacket</code> into which to place
  179.      *                 the incoming data.
  180.      * @exception  IOException  if an I/O error occurs.
  181.      * @see        java.net.DatagramPacket
  182.      * @see        java.net.DatagramSocket
  183.      * @since      JDK1.0
  184.      */
  185.     public synchronized void receive(DatagramPacket p) throws IOException {
  186.     // check the address is ok with the security manager before every recv.
  187.     SecurityManager security = System.getSecurityManager();
  188.  
  189.           synchronized (p) {
  190.         if (security != null) {
  191.  
  192.         while(true) {
  193.             // peek at the packet to see who it is from.
  194.             InetAddress peekAddress = new InetAddress();
  195.             int peekPort = impl.peek(peekAddress);
  196.  
  197.             try {
  198.             security.checkConnect(peekAddress.getHostAddress(), peekPort);
  199.             // security check succeeded - so now break and recv the packet.
  200.             break;
  201.             } catch (SecurityException se) {
  202.             // Throw away the offending packet by consuming
  203.             // it in a tmp buffer.
  204.             DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
  205.             impl.receive(tmp);
  206.  
  207.                 // silently discard the offending packet and continue:
  208.             // unknown/malicious entities on nets should not make
  209.             // runtime throw security exception and disrupt the applet
  210.             // by sending random datagram packets.
  211.             continue;
  212.             } 
  213.         } // end of while
  214.         }
  215.         // If the security check succeeds, then receive the packet
  216.          impl.receive(p);
  217.     }    
  218.     }
  219.  
  220.     /**
  221.      * Gets the local address to which the socket is bound.
  222.      *
  223.      * @since   1.1
  224.      */
  225.     public InetAddress getLocalAddress() {
  226.     InetAddress in = null;
  227.     try {
  228.         in = (InetAddress) impl.getOption(SocketOptions.SO_BINDADDR);
  229.         SecurityManager s = System.getSecurityManager();
  230.         if (s != null) {
  231.         s.checkConnect(in.getHostAddress(), -1);
  232.         }
  233.     } catch (Exception e) {
  234.         in = InetAddress.anyLocalAddress; // "0.0.0.0"
  235.     }
  236.     return in;
  237.     }    
  238.  
  239.     /**
  240.      * Returns the port number on the local host to which this socket is bound.
  241.      *
  242.      * @return  the port number on the local host to which this socket is bound.
  243.      * @since   JDK1.0
  244.      */
  245.     public int getLocalPort() {
  246.     return impl.getLocalPort();
  247.     }
  248.  
  249.     /** Enable/disable SO_TIMEOUT with the specified timeout, in
  250.      *  milliseconds. With this option set to a non-zero timeout,
  251.      *  a call to receive() for this DatagramSocket
  252.      *  will block for only this amount of time.  If the timeout expires,
  253.      *  a <B>java.io.InterruptedIOException</B> is raised, though the
  254.      *  ServerSocket is still valid.  The option <B>must</B> be enabled
  255.      *  prior to entering the blocking operation to have effect.  The 
  256.      *  timeout must be > 0.
  257.      *  A timeout of zero is interpreted as an infinite timeout.  
  258.      *
  259.      * @since   JDK1.1
  260.      */
  261.     public synchronized void setSoTimeout(int timeout) throws SocketException {
  262.     impl.setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
  263.     }
  264.  
  265.     /**
  266.      * Retrive setting for SO_TIMEOUT.  0 returns implies that the
  267.      * option is disabled (i.e., timeout of infinity).
  268.      *
  269.      * @since   JDK1.1
  270.      */
  271.     public synchronized int getSoTimeout() throws SocketException {
  272.     Object o = impl.getOption(SocketOptions.SO_TIMEOUT);
  273.     /* extra type safety */
  274.     if (o instanceof Integer) {
  275.         return ((Integer) o).intValue();
  276.     } else {
  277.         return 0;
  278.     }
  279.     }
  280.  
  281.     /**
  282.      * Closes this datagram socket. 
  283.      *
  284.      * @since   JDK1.0
  285.      */
  286.     public void close() {
  287.     impl.close();
  288.     }
  289. }
  290.