jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1996-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 package java.net;
       
    26 
       
    27 import java.io.FileDescriptor;
       
    28 import java.io.IOException;
       
    29 import java.io.InterruptedIOException;
       
    30 import java.util.Enumeration;
       
    31 
       
    32 /**
       
    33  * Abstract datagram and multicast socket implementation base class.
       
    34  * Note: This is not a public class, so that applets cannot call
       
    35  * into the implementation directly and hence cannot bypass the
       
    36  * security checks present in the DatagramSocket and MulticastSocket
       
    37  * classes.
       
    38  *
       
    39  * @author Pavani Diwanji
       
    40  */
       
    41 
       
    42 abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
       
    43 {
       
    44     /* timeout value for receive() */
       
    45     int timeout = 0;
       
    46     boolean connected = false;
       
    47     private int trafficClass = 0;
       
    48     private InetAddress connectedAddress = null;
       
    49     private int connectedPort = -1;
       
    50 
       
    51     /* cached socket options */
       
    52     private int multicastInterface = 0;
       
    53     private boolean loopbackMode = true;
       
    54     private int ttl = -1;
       
    55 
       
    56     /**
       
    57      * Load net library into runtime.
       
    58      */
       
    59     static {
       
    60         java.security.AccessController.doPrivileged(
       
    61                   new sun.security.action.LoadLibraryAction("net"));
       
    62     }
       
    63 
       
    64     /**
       
    65      * Creates a datagram socket
       
    66      */
       
    67     protected synchronized void create() throws SocketException {
       
    68         fd = new FileDescriptor();
       
    69         datagramSocketCreate();
       
    70     }
       
    71 
       
    72     /**
       
    73      * Binds a datagram socket to a local port.
       
    74      */
       
    75     protected synchronized void bind(int lport, InetAddress laddr)
       
    76         throws SocketException {
       
    77         bind0(lport, laddr);
       
    78     }
       
    79 
       
    80     protected abstract void bind0(int lport, InetAddress laddr)
       
    81         throws SocketException;
       
    82 
       
    83     /**
       
    84      * Sends a datagram packet. The packet contains the data and the
       
    85      * destination address to send the packet to.
       
    86      * @param packet to be sent.
       
    87      */
       
    88     protected abstract void send(DatagramPacket p) throws IOException;
       
    89 
       
    90     /**
       
    91      * Connects a datagram socket to a remote destination. This associates the remote
       
    92      * address with the local socket so that datagrams may only be sent to this destination
       
    93      * and received from this destination.
       
    94      * @param address the remote InetAddress to connect to
       
    95      * @param port the remote port number
       
    96      */
       
    97     protected void connect(InetAddress address, int port) throws SocketException {
       
    98         connect0(address, port);
       
    99         connectedAddress = address;
       
   100         connectedPort = port;
       
   101         connected = true;
       
   102     }
       
   103 
       
   104     /**
       
   105      * Disconnects a previously connected socket. Does nothing if the socket was
       
   106      * not connected already.
       
   107      */
       
   108     protected void disconnect() {
       
   109         disconnect0(connectedAddress.family);
       
   110         connected = false;
       
   111         connectedAddress = null;
       
   112         connectedPort = -1;
       
   113     }
       
   114 
       
   115     /**
       
   116      * Peek at the packet to see who it is from.
       
   117      * @param return the address which the packet came from.
       
   118      */
       
   119     protected abstract int peek(InetAddress i) throws IOException;
       
   120     protected abstract int peekData(DatagramPacket p) throws IOException;
       
   121     /**
       
   122      * Receive the datagram packet.
       
   123      * @param Packet Received.
       
   124      */
       
   125     protected synchronized void receive(DatagramPacket p)
       
   126         throws IOException {
       
   127         receive0(p);
       
   128     }
       
   129 
       
   130     protected abstract void receive0(DatagramPacket p)
       
   131         throws IOException;
       
   132 
       
   133     /**
       
   134      * Set the TTL (time-to-live) option.
       
   135      * @param TTL to be set.
       
   136      */
       
   137     protected abstract void setTimeToLive(int ttl) throws IOException;
       
   138 
       
   139     /**
       
   140      * Get the TTL (time-to-live) option.
       
   141      */
       
   142     protected abstract int getTimeToLive() throws IOException;
       
   143 
       
   144     /**
       
   145      * Set the TTL (time-to-live) option.
       
   146      * @param TTL to be set.
       
   147      */
       
   148     protected abstract void setTTL(byte ttl) throws IOException;
       
   149 
       
   150     /**
       
   151      * Get the TTL (time-to-live) option.
       
   152      */
       
   153     protected abstract byte getTTL() throws IOException;
       
   154 
       
   155     /**
       
   156      * Join the multicast group.
       
   157      * @param multicast address to join.
       
   158      */
       
   159     protected void join(InetAddress inetaddr) throws IOException {
       
   160         join(inetaddr, null);
       
   161     }
       
   162 
       
   163     /**
       
   164      * Leave the multicast group.
       
   165      * @param multicast address to leave.
       
   166      */
       
   167     protected void leave(InetAddress inetaddr) throws IOException {
       
   168         leave(inetaddr, null);
       
   169     }
       
   170     /**
       
   171      * Join the multicast group.
       
   172      * @param multicast address to join.
       
   173      * @param netIf specifies the local interface to receive multicast
       
   174      *        datagram packets
       
   175      * @throws  IllegalArgumentException if mcastaddr is null or is a
       
   176      *          SocketAddress subclass not supported by this socket
       
   177      * @since 1.4
       
   178      */
       
   179 
       
   180     protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
       
   181         throws IOException {
       
   182         if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
       
   183             throw new IllegalArgumentException("Unsupported address type");
       
   184         join(((InetSocketAddress)mcastaddr).getAddress(), netIf);
       
   185     }
       
   186 
       
   187     protected abstract void join(InetAddress inetaddr, NetworkInterface netIf)
       
   188         throws IOException;
       
   189 
       
   190     /**
       
   191      * Leave the multicast group.
       
   192      * @param multicast address to leave.
       
   193      * @param netIf specified the local interface to leave the group at
       
   194      * @throws  IllegalArgumentException if mcastaddr is null or is a
       
   195      *          SocketAddress subclass not supported by this socket
       
   196      * @since 1.4
       
   197      */
       
   198     protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
       
   199         throws IOException {
       
   200         if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress))
       
   201             throw new IllegalArgumentException("Unsupported address type");
       
   202         leave(((InetSocketAddress)mcastaddr).getAddress(), netIf);
       
   203     }
       
   204 
       
   205     protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf)
       
   206         throws IOException;
       
   207 
       
   208     /**
       
   209      * Close the socket.
       
   210      */
       
   211     protected void close() {
       
   212         if (fd != null) {
       
   213             datagramSocketClose();
       
   214             fd = null;
       
   215         }
       
   216     }
       
   217 
       
   218     protected boolean isClosed() {
       
   219         return (fd == null) ? true : false;
       
   220     }
       
   221 
       
   222     protected void finalize() {
       
   223         close();
       
   224     }
       
   225 
       
   226     /**
       
   227      * set a value - since we only support (setting) binary options
       
   228      * here, o must be a Boolean
       
   229      */
       
   230 
       
   231      public void setOption(int optID, Object o) throws SocketException {
       
   232          if (isClosed()) {
       
   233              throw new SocketException("Socket Closed");
       
   234          }
       
   235          switch (optID) {
       
   236             /* check type safety b4 going native.  These should never
       
   237              * fail, since only java.Socket* has access to
       
   238              * PlainSocketImpl.setOption().
       
   239              */
       
   240          case SO_TIMEOUT:
       
   241              if (o == null || !(o instanceof Integer)) {
       
   242                  throw new SocketException("bad argument for SO_TIMEOUT");
       
   243              }
       
   244              int tmp = ((Integer) o).intValue();
       
   245              if (tmp < 0)
       
   246                  throw new IllegalArgumentException("timeout < 0");
       
   247              timeout = tmp;
       
   248              return;
       
   249          case IP_TOS:
       
   250              if (o == null || !(o instanceof Integer)) {
       
   251                  throw new SocketException("bad argument for IP_TOS");
       
   252              }
       
   253              trafficClass = ((Integer)o).intValue();
       
   254              break;
       
   255          case SO_REUSEADDR:
       
   256              if (o == null || !(o instanceof Boolean)) {
       
   257                  throw new SocketException("bad argument for SO_REUSEADDR");
       
   258              }
       
   259              break;
       
   260          case SO_BROADCAST:
       
   261              if (o == null || !(o instanceof Boolean)) {
       
   262                  throw new SocketException("bad argument for SO_BROADCAST");
       
   263              }
       
   264              break;
       
   265          case SO_BINDADDR:
       
   266              throw new SocketException("Cannot re-bind Socket");
       
   267          case SO_RCVBUF:
       
   268          case SO_SNDBUF:
       
   269              if (o == null || !(o instanceof Integer) ||
       
   270                  ((Integer)o).intValue() < 0) {
       
   271                  throw new SocketException("bad argument for SO_SNDBUF or " +
       
   272                                            "SO_RCVBUF");
       
   273              }
       
   274              break;
       
   275          case IP_MULTICAST_IF:
       
   276              if (o == null || !(o instanceof InetAddress))
       
   277                  throw new SocketException("bad argument for IP_MULTICAST_IF");
       
   278              break;
       
   279          case IP_MULTICAST_IF2:
       
   280              if (o == null || !(o instanceof NetworkInterface))
       
   281                  throw new SocketException("bad argument for IP_MULTICAST_IF2");
       
   282              break;
       
   283          case IP_MULTICAST_LOOP:
       
   284              if (o == null || !(o instanceof Boolean))
       
   285                  throw new SocketException("bad argument for IP_MULTICAST_LOOP");
       
   286              break;
       
   287          default:
       
   288              throw new SocketException("invalid option: " + optID);
       
   289          }
       
   290          socketSetOption(optID, o);
       
   291      }
       
   292 
       
   293     /*
       
   294      * get option's state - set or not
       
   295      */
       
   296 
       
   297     public Object getOption(int optID) throws SocketException {
       
   298         if (isClosed()) {
       
   299             throw new SocketException("Socket Closed");
       
   300         }
       
   301 
       
   302         Object result;
       
   303 
       
   304         switch (optID) {
       
   305             case SO_TIMEOUT:
       
   306                 result = new Integer(timeout);
       
   307                 break;
       
   308 
       
   309             case IP_TOS:
       
   310                 result = socketGetOption(optID);
       
   311                 if ( ((Integer)result).intValue() == -1) {
       
   312                     result = new Integer(trafficClass);
       
   313                 }
       
   314                 break;
       
   315 
       
   316             case SO_BINDADDR:
       
   317             case IP_MULTICAST_IF:
       
   318             case IP_MULTICAST_IF2:
       
   319             case SO_RCVBUF:
       
   320             case SO_SNDBUF:
       
   321             case IP_MULTICAST_LOOP:
       
   322             case SO_REUSEADDR:
       
   323             case SO_BROADCAST:
       
   324                 result = socketGetOption(optID);
       
   325                 break;
       
   326 
       
   327             default:
       
   328                 throw new SocketException("invalid option: " + optID);
       
   329         }
       
   330 
       
   331         return result;
       
   332     }
       
   333 
       
   334     protected abstract void datagramSocketCreate() throws SocketException;
       
   335     protected abstract void datagramSocketClose();
       
   336     protected abstract void socketSetOption(int opt, Object val)
       
   337         throws SocketException;
       
   338     protected abstract Object socketGetOption(int opt) throws SocketException;
       
   339 
       
   340     protected abstract void connect0(InetAddress address, int port) throws SocketException;
       
   341     protected abstract void disconnect0(int family);
       
   342 
       
   343 }