PageRenderTime 51ms CodeModel.GetById 3ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 0ms

/jdk/src/share/classes/java/net/Socket.java

https://bitbucket.org/nkabir/jdk-6
Java | 1594 lines | 551 code | 81 blank | 962 comment | 134 complexity | b9f54c64fdb892bca55b83d7bfdde8fc MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
   3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4 *
   5 * This code is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License version 2 only, as
   7 * published by the Free Software Foundation.  Oracle designates this
   8 * particular file as subject to the "Classpath" exception as provided
   9 * by Oracle in the LICENSE file that accompanied this code.
  10 *
  11 * This code is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14 * version 2 for more details (a copy is included in the LICENSE file that
  15 * accompanied this code).
  16 *
  17 * You should have received a copy of the GNU General Public License version
  18 * 2 along with this work; if not, write to the Free Software Foundation,
  19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20 *
  21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22 * or visit www.oracle.com if you need additional information or have any
  23 * questions.
  24 */
  25
  26package java.net;
  27
  28import java.io.InputStream;
  29import java.io.OutputStream;
  30import java.io.IOException;
  31import java.io.InterruptedIOException;
  32import java.nio.channels.SocketChannel;
  33import java.security.AccessController;
  34import java.security.PrivilegedExceptionAction;
  35import java.security.PrivilegedAction;
  36
  37/**
  38 * This class implements client sockets (also called just
  39 * "sockets"). A socket is an endpoint for communication
  40 * between two machines.
  41 * <p>
  42 * The actual work of the socket is performed by an instance of the
  43 * <code>SocketImpl</code> class. An application, by changing
  44 * the socket factory that creates the socket implementation,
  45 * can configure itself to create sockets appropriate to the local
  46 * firewall.
  47 *
  48 * @author  unascribed
  49 * @see     java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  50 * @see     java.net.SocketImpl
  51 * @see     java.nio.channels.SocketChannel
  52 * @since   JDK1.0
  53 */
  54public
  55class Socket {
  56    /**
  57     * Various states of this socket.
  58     */
  59    private boolean created = false;
  60    private boolean bound = false;
  61    private boolean connected = false;
  62    private boolean closed = false;
  63    private Object closeLock = new Object();
  64    private boolean shutIn = false;
  65    private boolean shutOut = false;
  66
  67    /**
  68     * The implementation of this Socket.
  69     */
  70    SocketImpl impl;
  71
  72    /**
  73     * Are we using an older SocketImpl?
  74     */
  75    private boolean oldImpl = false;
  76
  77    /**
  78     * Creates an unconnected socket, with the
  79     * system-default type of SocketImpl.
  80     *
  81     * @since   JDK1.1
  82     * @revised 1.4
  83     */
  84    public Socket() {
  85        setImpl();
  86    }
  87
  88    /**
  89     * Creates an unconnected socket, specifying the type of proxy, if any,
  90     * that should be used regardless of any other settings.
  91     * <P>
  92     * If there is a security manager, its <code>checkConnect</code> method
  93     * is called with the proxy host address and port number
  94     * as its arguments. This could result in a SecurityException.
  95     * <P>
  96     * Examples:
  97     * <UL> <LI><code>Socket s = new Socket(Proxy.NO_PROXY);</code> will create
  98     * a plain socket ignoring any other proxy configuration.</LI>
  99     * <LI><code>Socket s = new Socket(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("socks.mydom.com", 1080)));</code>
 100     * will create a socket connecting through the specified SOCKS proxy
 101     * server.</LI>
 102     * </UL>
 103     *
 104     * @param proxy a {@link java.net.Proxy Proxy} object specifying what kind
 105     *              of proxying should be used.
 106     * @throws IllegalArgumentException if the proxy is of an invalid type
 107     *          or <code>null</code>.
 108     * @throws SecurityException if a security manager is present and
 109     *                           permission to connect to the proxy is
 110     *                           denied.
 111     * @see java.net.ProxySelector
 112     * @see java.net.Proxy
 113     *
 114     * @since   1.5
 115     */
 116    public Socket(Proxy proxy) {
 117        // Create a copy of Proxy as a security measure
 118        if (proxy == null) {
 119            throw new IllegalArgumentException("Invalid Proxy");
 120        }
 121        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
 122        if (p.type() == Proxy.Type.SOCKS) {
 123            SecurityManager security = System.getSecurityManager();
 124            InetSocketAddress epoint = (InetSocketAddress) p.address();
 125            if (epoint.getAddress() != null) {
 126                checkAddress (epoint.getAddress(), "Socket");
 127            }
 128            if (security != null) {
 129                if (epoint.isUnresolved())
 130                    epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());
 131                if (epoint.isUnresolved())
 132                    security.checkConnect(epoint.getHostName(),
 133                                          epoint.getPort());
 134                else
 135                    security.checkConnect(epoint.getAddress().getHostAddress(),
 136                                          epoint.getPort());
 137            }
 138            impl = new SocksSocketImpl(p);
 139            impl.setSocket(this);
 140        } else {
 141            if (p == Proxy.NO_PROXY) {
 142                if (factory == null) {
 143                    impl = new PlainSocketImpl();
 144                    impl.setSocket(this);
 145                } else
 146                    setImpl();
 147            } else
 148                throw new IllegalArgumentException("Invalid Proxy");
 149        }
 150    }
 151
 152    /**
 153     * Creates an unconnected Socket with a user-specified
 154     * SocketImpl.
 155     * <P>
 156     * @param impl an instance of a <B>SocketImpl</B>
 157     * the subclass wishes to use on the Socket.
 158     *
 159     * @exception SocketException if there is an error in the underlying protocol,
 160     * such as a TCP error.
 161     * @since   JDK1.1
 162     */
 163    protected Socket(SocketImpl impl) throws SocketException {
 164        this.impl = impl;
 165        if (impl != null) {
 166            checkOldImpl();
 167            this.impl.setSocket(this);
 168        }
 169    }
 170
 171    /**
 172     * Creates a stream socket and connects it to the specified port
 173     * number on the named host.
 174     * <p>
 175     * If the specified host is <tt>null</tt> it is the equivalent of
 176     * specifying the address as <tt>{@link java.net.InetAddress#getByName InetAddress.getByName}(null)</tt>.
 177     * In other words, it is equivalent to specifying an address of the
 178     * loopback interface. </p>
 179     * <p>
 180     * If the application has specified a server socket factory, that
 181     * factory's <code>createSocketImpl</code> method is called to create
 182     * the actual socket implementation. Otherwise a "plain" socket is created.
 183     * <p>
 184     * If there is a security manager, its
 185     * <code>checkConnect</code> method is called
 186     * with the host address and <code>port</code>
 187     * as its arguments. This could result in a SecurityException.
 188     *
 189     * @param      host   the host name, or <code>null</code> for the loopback address.
 190     * @param      port   the port number.
 191     *
 192     * @exception  UnknownHostException if the IP address of
 193     * the host could not be determined.
 194     *
 195     * @exception  IOException  if an I/O error occurs when creating the socket.
 196     * @exception  SecurityException  if a security manager exists and its
 197     *             <code>checkConnect</code> method doesn't allow the operation.
 198     * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
 199     * @see        java.net.SocketImpl
 200     * @see        java.net.SocketImplFactory#createSocketImpl()
 201     * @see        SecurityManager#checkConnect
 202     */
 203    public Socket(String host, int port)
 204        throws UnknownHostException, IOException
 205    {
 206        this(host != null ? new InetSocketAddress(host, port) :
 207             new InetSocketAddress(InetAddress.getByName(null), port),
 208             (SocketAddress) null, true);
 209    }
 210
 211    /**
 212     * Creates a stream socket and connects it to the specified port
 213     * number at the specified IP address.
 214     * <p>
 215     * If the application has specified a socket factory, that factory's
 216     * <code>createSocketImpl</code> method is called to create the
 217     * actual socket implementation. Otherwise a "plain" socket is created.
 218     * <p>
 219     * If there is a security manager, its
 220     * <code>checkConnect</code> method is called
 221     * with the host address and <code>port</code>
 222     * as its arguments. This could result in a SecurityException.
 223     *
 224     * @param      address   the IP address.
 225     * @param      port      the port number.
 226     * @exception  IOException  if an I/O error occurs when creating the socket.
 227     * @exception  SecurityException  if a security manager exists and its
 228     *             <code>checkConnect</code> method doesn't allow the operation.
 229     * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
 230     * @see        java.net.SocketImpl
 231     * @see        java.net.SocketImplFactory#createSocketImpl()
 232     * @see        SecurityManager#checkConnect
 233     */
 234    public Socket(InetAddress address, int port) throws IOException {
 235        this(address != null ? new InetSocketAddress(address, port) : null,
 236             (SocketAddress) null, true);
 237    }
 238
 239    /**
 240     * Creates a socket and connects it to the specified remote host on
 241     * the specified remote port. The Socket will also bind() to the local
 242     * address and port supplied.
 243     * <p>
 244     * If the specified host is <tt>null</tt> it is the equivalent of
 245     * specifying the address as <tt>{@link java.net.InetAddress#getByName InetAddress.getByName}(null)</tt>.
 246     * In other words, it is equivalent to specifying an address of the
 247     * loopback interface. </p>
 248     * <p>
 249     * If there is a security manager, its
 250     * <code>checkConnect</code> method is called
 251     * with the host address and <code>port</code>
 252     * as its arguments. This could result in a SecurityException.
 253     *
 254     * @param host the name of the remote host, or <code>null</code> for the loopback address.
 255     * @param port the remote port
 256     * @param localAddr the local address the socket is bound to
 257     * @param localPort the local port the socket is bound to
 258     * @exception  IOException  if an I/O error occurs when creating the socket.
 259     * @exception  SecurityException  if a security manager exists and its
 260     *             <code>checkConnect</code> method doesn't allow the operation.
 261     * @see        SecurityManager#checkConnect
 262     * @since   JDK1.1
 263     */
 264    public Socket(String host, int port, InetAddress localAddr,
 265                  int localPort) throws IOException {
 266        this(host != null ? new InetSocketAddress(host, port) :
 267               new InetSocketAddress(InetAddress.getByName(null), port),
 268             new InetSocketAddress(localAddr, localPort), true);
 269    }
 270
 271    /**
 272     * Creates a socket and connects it to the specified remote address on
 273     * the specified remote port. The Socket will also bind() to the local
 274     * address and port supplied.
 275     * <p>
 276     * If there is a security manager, its
 277     * <code>checkConnect</code> method is called
 278     * with the host address and <code>port</code>
 279     * as its arguments. This could result in a SecurityException.
 280     *
 281     * @param address the remote address
 282     * @param port the remote port
 283     * @param localAddr the local address the socket is bound to
 284     * @param localPort the local port the socket is bound to
 285     * @exception  IOException  if an I/O error occurs when creating the socket.
 286     * @exception  SecurityException  if a security manager exists and its
 287     *             <code>checkConnect</code> method doesn't allow the operation.
 288     * @see        SecurityManager#checkConnect
 289     * @since   JDK1.1
 290     */
 291    public Socket(InetAddress address, int port, InetAddress localAddr,
 292                  int localPort) throws IOException {
 293        this(address != null ? new InetSocketAddress(address, port) : null,
 294             new InetSocketAddress(localAddr, localPort), true);
 295    }
 296
 297    /**
 298     * Creates a stream socket and connects it to the specified port
 299     * number on the named host.
 300     * <p>
 301     * If the specified host is <tt>null</tt> it is the equivalent of
 302     * specifying the address as <tt>{@link java.net.InetAddress#getByName InetAddress.getByName}(null)</tt>.
 303     * In other words, it is equivalent to specifying an address of the
 304     * loopback interface. </p>
 305     * <p>
 306     * If the stream argument is <code>true</code>, this creates a
 307     * stream socket. If the stream argument is <code>false</code>, it
 308     * creates a datagram socket.
 309     * <p>
 310     * If the application has specified a server socket factory, that
 311     * factory's <code>createSocketImpl</code> method is called to create
 312     * the actual socket implementation. Otherwise a "plain" socket is created.
 313     * <p>
 314     * If there is a security manager, its
 315     * <code>checkConnect</code> method is called
 316     * with the host address and <code>port</code>
 317     * as its arguments. This could result in a SecurityException.
 318     * <p>
 319     * If a UDP socket is used, TCP/IP related socket options will not apply.
 320     *
 321     * @param      host     the host name, or <code>null</code> for the loopback address.
 322     * @param      port     the port number.
 323     * @param      stream   a <code>boolean</code> indicating whether this is
 324     *                      a stream socket or a datagram socket.
 325     * @exception  IOException  if an I/O error occurs when creating the socket.
 326     * @exception  SecurityException  if a security manager exists and its
 327     *             <code>checkConnect</code> method doesn't allow the operation.
 328     * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
 329     * @see        java.net.SocketImpl
 330     * @see        java.net.SocketImplFactory#createSocketImpl()
 331     * @see        SecurityManager#checkConnect
 332     * @deprecated Use DatagramSocket instead for UDP transport.
 333     */
 334    @Deprecated
 335    public Socket(String host, int port, boolean stream) throws IOException {
 336        this(host != null ? new InetSocketAddress(host, port) :
 337               new InetSocketAddress(InetAddress.getByName(null), port),
 338             (SocketAddress) null, stream);
 339    }
 340
 341    /**
 342     * Creates a socket and connects it to the specified port number at
 343     * the specified IP address.
 344     * <p>
 345     * If the stream argument is <code>true</code>, this creates a
 346     * stream socket. If the stream argument is <code>false</code>, it
 347     * creates a datagram socket.
 348     * <p>
 349     * If the application has specified a server socket factory, that
 350     * factory's <code>createSocketImpl</code> method is called to create
 351     * the actual socket implementation. Otherwise a "plain" socket is created.
 352     *
 353     * <p>If there is a security manager, its
 354     * <code>checkConnect</code> method is called
 355     * with <code>host.getHostAddress()</code> and <code>port</code>
 356     * as its arguments. This could result in a SecurityException.
 357     * <p>
 358     * If UDP socket is used, TCP/IP related socket options will not apply.
 359     *
 360     * @param      host     the IP address.
 361     * @param      port      the port number.
 362     * @param      stream    if <code>true</code>, create a stream socket;
 363     *                       otherwise, create a datagram socket.
 364     * @exception  IOException  if an I/O error occurs when creating the socket.
 365     * @exception  SecurityException  if a security manager exists and its
 366     *             <code>checkConnect</code> method doesn't allow the operation.
 367     * @see        java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
 368     * @see        java.net.SocketImpl
 369     * @see        java.net.SocketImplFactory#createSocketImpl()
 370     * @see        SecurityManager#checkConnect
 371     * @deprecated Use DatagramSocket instead for UDP transport.
 372     */
 373    @Deprecated
 374    public Socket(InetAddress host, int port, boolean stream) throws IOException {
 375        this(host != null ? new InetSocketAddress(host, port) : null,
 376             new InetSocketAddress(0), stream);
 377    }
 378
 379    private Socket(SocketAddress address, SocketAddress localAddr,
 380                   boolean stream) throws IOException {
 381        setImpl();
 382
 383        // backward compatibility
 384        if (address == null)
 385            throw new NullPointerException();
 386
 387        try {
 388            createImpl(stream);
 389            if (localAddr != null)
 390                bind(localAddr);
 391            if (address != null)
 392                connect(address);
 393        } catch (IOException e) {
 394            close();
 395            throw e;
 396        }
 397    }
 398
 399    /**
 400     * Creates the socket implementation.
 401     *
 402     * @param stream a <code>boolean</code> value : <code>true</code> for a TCP socket,
 403     *               <code>false</code> for UDP.
 404     * @throws IOException if creation fails
 405     * @since 1.4
 406     */
 407     void createImpl(boolean stream) throws SocketException {
 408        if (impl == null)
 409            setImpl();
 410        try {
 411            impl.create(stream);
 412            created = true;
 413        } catch (IOException e) {
 414            throw new SocketException(e.getMessage());
 415        }
 416    }
 417
 418    private void checkOldImpl() {
 419        if (impl == null)
 420            return;
 421        // SocketImpl.connect() is a protected method, therefore we need to use
 422        // getDeclaredMethod, therefore we need permission to access the member
 423
 424        oldImpl = AccessController.doPrivileged
 425                                (new PrivilegedAction<Boolean>() {
 426            public Boolean run() {
 427                Class[] cl = new Class[2];
 428                cl[0] = SocketAddress.class;
 429                cl[1] = Integer.TYPE;
 430                Class clazz = impl.getClass();
 431                while (true) {
 432                    try {
 433                        clazz.getDeclaredMethod("connect", cl);
 434                        return Boolean.FALSE;
 435                    } catch (NoSuchMethodException e) {
 436                        clazz = clazz.getSuperclass();
 437                        // java.net.SocketImpl class will always have this abstract method.
 438                        // If we have not found it by now in the hierarchy then it does not
 439                        // exist, we are an old style impl.
 440                        if (clazz.equals(java.net.SocketImpl.class)) {
 441                            return Boolean.TRUE;
 442                        }
 443                    }
 444                }
 445            }
 446        });
 447    }
 448
 449    /**
 450     * Sets impl to the system-default type of SocketImpl.
 451     * @since 1.4
 452     */
 453    void setImpl() {
 454        if (factory != null) {
 455            impl = factory.createSocketImpl();
 456            checkOldImpl();
 457        } else {
 458            // No need to do a checkOldImpl() here, we know it's an up to date
 459            // SocketImpl!
 460            impl = new SocksSocketImpl();
 461        }
 462        if (impl != null)
 463            impl.setSocket(this);
 464    }
 465
 466
 467    /**
 468     * Get the <code>SocketImpl</code> attached to this socket, creating
 469     * it if necessary.
 470     *
 471     * @return  the <code>SocketImpl</code> attached to that ServerSocket.
 472     * @throws SocketException if creation fails
 473     * @since 1.4
 474     */
 475    SocketImpl getImpl() throws SocketException {
 476        if (!created)
 477            createImpl(true);
 478        return impl;
 479    }
 480
 481    /**
 482     * Connects this socket to the server.
 483     *
 484     * @param   endpoint the <code>SocketAddress</code>
 485     * @throws  IOException if an error occurs during the connection
 486     * @throws  java.nio.channels.IllegalBlockingModeException
 487     *          if this socket has an associated channel,
 488     *          and the channel is in non-blocking mode
 489     * @throws  IllegalArgumentException if endpoint is null or is a
 490     *          SocketAddress subclass not supported by this socket
 491     * @since 1.4
 492     * @spec JSR-51
 493     */
 494    public void connect(SocketAddress endpoint) throws IOException {
 495        connect(endpoint, 0);
 496    }
 497
 498    /**
 499     * Connects this socket to the server with a specified timeout value.
 500     * A timeout of zero is interpreted as an infinite timeout. The connection
 501     * will then block until established or an error occurs.
 502     *
 503     * @param   endpoint the <code>SocketAddress</code>
 504     * @param   timeout  the timeout value to be used in milliseconds.
 505     * @throws  IOException if an error occurs during the connection
 506     * @throws  SocketTimeoutException if timeout expires before connecting
 507     * @throws  java.nio.channels.IllegalBlockingModeException
 508     *          if this socket has an associated channel,
 509     *          and the channel is in non-blocking mode
 510     * @throws  IllegalArgumentException if endpoint is null or is a
 511     *          SocketAddress subclass not supported by this socket
 512     * @since 1.4
 513     * @spec JSR-51
 514     */
 515    public void connect(SocketAddress endpoint, int timeout) throws IOException {
 516        if (endpoint == null)
 517            throw new IllegalArgumentException("connect: The address can't be null");
 518
 519        if (timeout < 0)
 520          throw new IllegalArgumentException("connect: timeout can't be negative");
 521
 522        if (isClosed())
 523            throw new SocketException("Socket is closed");
 524
 525        if (!oldImpl && isConnected())
 526            throw new SocketException("already connected");
 527
 528        if (!(endpoint instanceof InetSocketAddress))
 529            throw new IllegalArgumentException("Unsupported address type");
 530
 531        InetSocketAddress epoint = (InetSocketAddress) endpoint;
 532        InetAddress addr = epoint.getAddress ();
 533        int port = epoint.getPort();
 534        checkAddress(addr, "connect");
 535
 536        SecurityManager security = System.getSecurityManager();
 537        if (security != null) {
 538            if (epoint.isUnresolved())
 539                security.checkConnect(epoint.getHostName(), port);
 540            else
 541                security.checkConnect(addr.getHostAddress(), port);
 542        }
 543        if (!created)
 544            createImpl(true);
 545        if (!oldImpl)
 546            impl.connect(epoint, timeout);
 547        else if (timeout == 0) {
 548            if (epoint.isUnresolved())
 549                impl.connect(addr.getHostName(), port);
 550            else
 551                impl.connect(addr, port);
 552        } else
 553            throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
 554        connected = true;
 555        /*
 556         * If the socket was not bound before the connect, it is now because
 557         * the kernel will have picked an ephemeral port & a local address
 558         */
 559        bound = true;
 560    }
 561
 562    /**
 563     * Binds the socket to a local address.
 564     * <P>
 565     * If the address is <code>null</code>, then the system will pick up
 566     * an ephemeral port and a valid local address to bind the socket.
 567     *
 568     * @param   bindpoint the <code>SocketAddress</code> to bind to
 569     * @throws  IOException if the bind operation fails, or if the socket
 570     *                     is already bound.
 571     * @throws  IllegalArgumentException if bindpoint is a
 572     *          SocketAddress subclass not supported by this socket
 573     *
 574     * @since   1.4
 575     * @see #isBound
 576     */
 577    public void bind(SocketAddress bindpoint) throws IOException {
 578        if (isClosed())
 579            throw new SocketException("Socket is closed");
 580        if (!oldImpl && isBound())
 581            throw new SocketException("Already bound");
 582
 583        if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
 584            throw new IllegalArgumentException("Unsupported address type");
 585        InetSocketAddress epoint = (InetSocketAddress) bindpoint;
 586        if (epoint != null && epoint.isUnresolved())
 587            throw new SocketException("Unresolved address");
 588        if (epoint == null) {
 589            epoint = new InetSocketAddress(0);
 590        }
 591        InetAddress addr = epoint.getAddress();
 592        int port = epoint.getPort();
 593        checkAddress (addr, "bind");
 594        getImpl().bind (addr, port);
 595        bound = true;
 596    }
 597
 598    private void checkAddress (InetAddress addr, String op) {
 599        if (addr == null) {
 600            return;
 601        }
 602        if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
 603            throw new IllegalArgumentException(op + ": invalid address type");
 604        }
 605    }
 606
 607    /**
 608     * set the flags after an accept() call.
 609     */
 610    final void postAccept() {
 611        connected = true;
 612        created = true;
 613        bound = true;
 614    }
 615
 616    void setCreated() {
 617        created = true;
 618    }
 619
 620    void setBound() {
 621        bound = true;
 622    }
 623
 624    void setConnected() {
 625        connected = true;
 626    }
 627
 628    /**
 629     * Returns the address to which the socket is connected.
 630     *
 631     * @return  the remote IP address to which this socket is connected,
 632     *          or <code>null</code> if the socket is not connected.
 633     */
 634    public InetAddress getInetAddress() {
 635        if (!isConnected())
 636            return null;
 637        try {
 638            return getImpl().getInetAddress();
 639        } catch (SocketException e) {
 640        }
 641        return null;
 642    }
 643
 644    /**
 645     * Gets the local address to which the socket is bound.
 646     *
 647     * @return the local address to which the socket is bound or
 648     *         <code>InetAddress.anyLocalAddress()</code>
 649     *         if the socket is not bound yet.
 650     * @since   JDK1.1
 651     */
 652    public InetAddress getLocalAddress() {
 653        // This is for backward compatibility
 654        if (!isBound())
 655            return InetAddress.anyLocalAddress();
 656        InetAddress in = null;
 657        try {
 658            in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
 659            if (in.isAnyLocalAddress()) {
 660                in = InetAddress.anyLocalAddress();
 661            }
 662        } catch (Exception e) {
 663            in = InetAddress.anyLocalAddress(); // "0.0.0.0"
 664        }
 665        return in;
 666    }
 667
 668    /**
 669     * Returns the remote port number to which this socket is connected.
 670     *
 671     * @return  the remote port number to which this socket is connected, or
 672     *          0 if the socket is not connected yet.
 673     */
 674    public int getPort() {
 675        if (!isConnected())
 676            return 0;
 677        try {
 678            return getImpl().getPort();
 679        } catch (SocketException e) {
 680            // Shouldn't happen as we're connected
 681        }
 682        return -1;
 683    }
 684
 685    /**
 686     * Returns the local port number to which this socket is bound.
 687     *
 688     * @return  the local port number to which this socket is bound or -1
 689     *          if the socket is not bound yet.
 690     */
 691    public int getLocalPort() {
 692        if (!isBound())
 693            return -1;
 694        try {
 695            return getImpl().getLocalPort();
 696        } catch(SocketException e) {
 697            // shouldn't happen as we're bound
 698        }
 699        return -1;
 700    }
 701
 702    /**
 703     * Returns the address of the endpoint this socket is connected to, or
 704     * <code>null</code> if it is unconnected.
 705     *
 706     * @return a <code>SocketAddress</code> reprensenting the remote endpoint of this
 707     *         socket, or <code>null</code> if it is not connected yet.
 708     * @see #getInetAddress()
 709     * @see #getPort()
 710     * @see #connect(SocketAddress, int)
 711     * @see #connect(SocketAddress)
 712     * @since 1.4
 713     */
 714    public SocketAddress getRemoteSocketAddress() {
 715        if (!isConnected())
 716            return null;
 717        return new InetSocketAddress(getInetAddress(), getPort());
 718    }
 719
 720    /**
 721     * Returns the address of the endpoint this socket is bound to, or
 722     * <code>null</code> if it is not bound yet.
 723     *
 724     * @return a <code>SocketAddress</code> representing the local endpoint of this
 725     *         socket, or <code>null</code> if it is not bound yet.
 726     * @see #getLocalAddress()
 727     * @see #getLocalPort()
 728     * @see #bind(SocketAddress)
 729     * @since 1.4
 730     */
 731
 732    public SocketAddress getLocalSocketAddress() {
 733        if (!isBound())
 734            return null;
 735        return new InetSocketAddress(getLocalAddress(), getLocalPort());
 736    }
 737
 738    /**
 739     * Returns the unique {@link java.nio.channels.SocketChannel SocketChannel}
 740     * object associated with this socket, if any.
 741     *
 742     * <p> A socket will have a channel if, and only if, the channel itself was
 743     * created via the {@link java.nio.channels.SocketChannel#open
 744     * SocketChannel.open} or {@link
 745     * java.nio.channels.ServerSocketChannel#accept ServerSocketChannel.accept}
 746     * methods.
 747     *
 748     * @return  the socket channel associated with this socket,
 749     *          or <tt>null</tt> if this socket was not created
 750     *          for a channel
 751     *
 752     * @since 1.4
 753     * @spec JSR-51
 754     */
 755    public SocketChannel getChannel() {
 756        return null;
 757    }
 758
 759    /**
 760     * Returns an input stream for this socket.
 761     *
 762     * <p> If this socket has an associated channel then the resulting input
 763     * stream delegates all of its operations to the channel.  If the channel
 764     * is in non-blocking mode then the input stream's <tt>read</tt> operations
 765     * will throw an {@link java.nio.channels.IllegalBlockingModeException}.
 766     *
 767     * <p>Under abnormal conditions the underlying connection may be
 768     * broken by the remote host or the network software (for example
 769     * a connection reset in the case of TCP connections). When a
 770     * broken connection is detected by the network software the
 771     * following applies to the returned input stream :-
 772     *
 773     * <ul>
 774     *
 775     *   <li><p>The network software may discard bytes that are buffered
 776     *   by the socket. Bytes that aren't discarded by the network
 777     *   software can be read using {@link java.io.InputStream#read read}.
 778     *
 779     *   <li><p>If there are no bytes buffered on the socket, or all
 780     *   buffered bytes have been consumed by
 781     *   {@link java.io.InputStream#read read}, then all subsequent
 782     *   calls to {@link java.io.InputStream#read read} will throw an
 783     *   {@link java.io.IOException IOException}.
 784     *
 785     *   <li><p>If there are no bytes buffered on the socket, and the
 786     *   socket has not been closed using {@link #close close}, then
 787     *   {@link java.io.InputStream#available available} will
 788     *   return <code>0</code>.
 789     *
 790     * </ul>
 791     *
 792     * <p> Closing the returned {@link java.io.InputStream InputStream}
 793     * will close the associated socket.
 794     *
 795     * @return     an input stream for reading bytes from this socket.
 796     * @exception  IOException  if an I/O error occurs when creating the
 797     *             input stream, the socket is closed, the socket is
 798     *             not connected, or the socket input has been shutdown
 799     *             using {@link #shutdownInput()}
 800     *
 801     * @revised 1.4
 802     * @spec JSR-51
 803     */
 804    public InputStream getInputStream() throws IOException {
 805        if (isClosed())
 806            throw new SocketException("Socket is closed");
 807        if (!isConnected())
 808            throw new SocketException("Socket is not connected");
 809        if (isInputShutdown())
 810            throw new SocketException("Socket input is shutdown");
 811        final Socket s = this;
 812        InputStream is = null;
 813        try {
 814            is = (InputStream)
 815                AccessController.doPrivileged(new PrivilegedExceptionAction() {
 816                    public Object run() throws IOException {
 817                        return impl.getInputStream();
 818                    }
 819                });
 820        } catch (java.security.PrivilegedActionException e) {
 821            throw (IOException) e.getException();
 822        }
 823        return is;
 824    }
 825
 826    /**
 827     * Returns an output stream for this socket.
 828     *
 829     * <p> If this socket has an associated channel then the resulting output
 830     * stream delegates all of its operations to the channel.  If the channel
 831     * is in non-blocking mode then the output stream's <tt>write</tt>
 832     * operations will throw an {@link
 833     * java.nio.channels.IllegalBlockingModeException}.
 834     *
 835     * <p> Closing the returned {@link java.io.OutputStream OutputStream}
 836     * will close the associated socket.
 837     *
 838     * @return     an output stream for writing bytes to this socket.
 839     * @exception  IOException  if an I/O error occurs when creating the
 840     *               output stream or if the socket is not connected.
 841     * @revised 1.4
 842     * @spec JSR-51
 843     */
 844    public OutputStream getOutputStream() throws IOException {
 845        if (isClosed())
 846            throw new SocketException("Socket is closed");
 847        if (!isConnected())
 848            throw new SocketException("Socket is not connected");
 849        if (isOutputShutdown())
 850            throw new SocketException("Socket output is shutdown");
 851        final Socket s = this;
 852        OutputStream os = null;
 853        try {
 854            os = (OutputStream)
 855                AccessController.doPrivileged(new PrivilegedExceptionAction() {
 856                    public Object run() throws IOException {
 857                        return impl.getOutputStream();
 858                    }
 859                });
 860        } catch (java.security.PrivilegedActionException e) {
 861            throw (IOException) e.getException();
 862        }
 863        return os;
 864    }
 865
 866    /**
 867     * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
 868     *
 869     * @param on <code>true</code> to enable TCP_NODELAY,
 870     * <code>false</code> to disable.
 871     *
 872     * @exception SocketException if there is an error
 873     * in the underlying protocol, such as a TCP error.
 874     *
 875     * @since   JDK1.1
 876     *
 877     * @see #getTcpNoDelay()
 878     */
 879    public void setTcpNoDelay(boolean on) throws SocketException {
 880        if (isClosed())
 881            throw new SocketException("Socket is closed");
 882        getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
 883    }
 884
 885    /**
 886     * Tests if TCP_NODELAY is enabled.
 887     *
 888     * @return a <code>boolean</code> indicating whether or not TCP_NODELAY is enabled.
 889     * @exception SocketException if there is an error
 890     * in the underlying protocol, such as a TCP error.
 891     * @since   JDK1.1
 892     * @see #setTcpNoDelay(boolean)
 893     */
 894    public boolean getTcpNoDelay() throws SocketException {
 895        if (isClosed())
 896            throw new SocketException("Socket is closed");
 897        return ((Boolean) getImpl().getOption(SocketOptions.TCP_NODELAY)).booleanValue();
 898    }
 899
 900    /**
 901     * Enable/disable SO_LINGER with the specified linger time in seconds.
 902     * The maximum timeout value is platform specific.
 903     *
 904     * The setting only affects socket close.
 905     *
 906     * @param on     whether or not to linger on.
 907     * @param linger how long to linger for, if on is true.
 908     * @exception SocketException if there is an error
 909     * in the underlying protocol, such as a TCP error.
 910     * @exception IllegalArgumentException if the linger value is negative.
 911     * @since JDK1.1
 912     * @see #getSoLinger()
 913     */
 914    public void setSoLinger(boolean on, int linger) throws SocketException {
 915        if (isClosed())
 916            throw new SocketException("Socket is closed");
 917        if (!on) {
 918            getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on));
 919        } else {
 920            if (linger < 0) {
 921                throw new IllegalArgumentException("invalid value for SO_LINGER");
 922            }
 923            if (linger > 65535)
 924                linger = 65535;
 925            getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
 926        }
 927    }
 928
 929    /**
 930     * Returns setting for SO_LINGER. -1 returns implies that the
 931     * option is disabled.
 932     *
 933     * The setting only affects socket close.
 934     *
 935     * @return the setting for SO_LINGER.
 936     * @exception SocketException if there is an error
 937     * in the underlying protocol, such as a TCP error.
 938     * @since   JDK1.1
 939     * @see #setSoLinger(boolean, int)
 940     */
 941    public int getSoLinger() throws SocketException {
 942        if (isClosed())
 943            throw new SocketException("Socket is closed");
 944        Object o = getImpl().getOption(SocketOptions.SO_LINGER);
 945        if (o instanceof Integer) {
 946            return ((Integer) o).intValue();
 947        } else {
 948            return -1;
 949        }
 950    }
 951
 952    /**
 953     * Send one byte of urgent data on the socket. The byte to be sent is the lowest eight
 954     * bits of the data parameter. The urgent byte is
 955     * sent after any preceding writes to the socket OutputStream
 956     * and before any future writes to the OutputStream.
 957     * @param data The byte of data to send
 958     * @exception IOException if there is an error
 959     *  sending the data.
 960     * @since 1.4
 961     */
 962    public void sendUrgentData (int data) throws IOException  {
 963        if (!getImpl().supportsUrgentData ()) {
 964            throw new SocketException ("Urgent data not supported");
 965        }
 966        getImpl().sendUrgentData (data);
 967    }
 968
 969    /**
 970     * Enable/disable OOBINLINE (receipt of TCP urgent data)
 971     *
 972     * By default, this option is disabled and TCP urgent data received on a
 973     * socket is silently discarded. If the user wishes to receive urgent data, then
 974     * this option must be enabled. When enabled, urgent data is received
 975     * inline with normal data.
 976     * <p>
 977     * Note, only limited support is provided for handling incoming urgent
 978     * data. In particular, no notification of incoming urgent data is provided
 979     * and there is no capability to distinguish between normal data and urgent
 980     * data unless provided by a higher level protocol.
 981     *
 982     * @param on <code>true</code> to enable OOBINLINE,
 983     * <code>false</code> to disable.
 984     *
 985     * @exception SocketException if there is an error
 986     * in the underlying protocol, such as a TCP error.
 987     *
 988     * @since   1.4
 989     *
 990     * @see #getOOBInline()
 991     */
 992    public void setOOBInline(boolean on) throws SocketException {
 993        if (isClosed())
 994            throw new SocketException("Socket is closed");
 995        getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
 996    }
 997
 998    /**
 999     * Tests if OOBINLINE is enabled.
1000     *
1001     * @return a <code>boolean</code> indicating whether or not OOBINLINE is enabled.
1002     * @exception SocketException if there is an error
1003     * in the underlying protocol, such as a TCP error.
1004     * @since   1.4
1005     * @see #setOOBInline(boolean)
1006     */
1007    public boolean getOOBInline() throws SocketException {
1008        if (isClosed())
1009            throw new SocketException("Socket is closed");
1010        return ((Boolean) getImpl().getOption(SocketOptions.SO_OOBINLINE)).booleanValue();
1011    }
1012
1013    /**
1014     *  Enable/disable SO_TIMEOUT with the specified timeout, in
1015     *  milliseconds.  With this option set to a non-zero timeout,
1016     *  a read() call on the InputStream associated with this Socket
1017     *  will block for only this amount of time.  If the timeout expires,
1018     *  a <B>java.net.SocketTimeoutException</B> is raised, though the
1019     *  Socket is still valid. The option <B>must</B> be enabled
1020     *  prior to entering the blocking operation to have effect. The
1021     *  timeout must be > 0.
1022     *  A timeout of zero is interpreted as an infinite timeout.
1023     * @param timeout the specified timeout, in milliseconds.
1024     * @exception SocketException if there is an error
1025     * in the underlying protocol, such as a TCP error.
1026     * @since   JDK 1.1
1027     * @see #getSoTimeout()
1028     */
1029    public synchronized void setSoTimeout(int timeout) throws SocketException {
1030        if (isClosed())
1031            throw new SocketException("Socket is closed");
1032        if (timeout < 0)
1033          throw new IllegalArgumentException("timeout can't be negative");
1034
1035        getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
1036    }
1037
1038    /**
1039     * Returns setting for SO_TIMEOUT.  0 returns implies that the
1040     * option is disabled (i.e., timeout of infinity).
1041     * @return the setting for SO_TIMEOUT
1042     * @exception SocketException if there is an error
1043     * in the underlying protocol, such as a TCP error.
1044     * @since   JDK1.1
1045     * @see #setSoTimeout(int)
1046     */
1047    public synchronized int getSoTimeout() throws SocketException {
1048        if (isClosed())
1049            throw new SocketException("Socket is closed");
1050        Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT);
1051        /* extra type safety */
1052        if (o instanceof Integer) {
1053            return ((Integer) o).intValue();
1054        } else {
1055            return 0;
1056        }
1057    }
1058
1059    /**
1060     * Sets the SO_SNDBUF option to the specified value for this
1061     * <tt>Socket</tt>. The SO_SNDBUF option is used by the platform's
1062     * networking code as a hint for the size to set
1063     * the underlying network I/O buffers.
1064     *
1065     * <p>Because SO_SNDBUF is a hint, applications that want to
1066     * verify what size the buffers were set to should call
1067     * {@link #getSendBufferSize()}.
1068     *
1069     * @exception SocketException if there is an error
1070     * in the underlying protocol, such as a TCP error.
1071     *
1072     * @param size the size to which to set the send buffer
1073     * size. This value must be greater than 0.
1074     *
1075     * @exception IllegalArgumentException if the
1076     * value is 0 or is negative.
1077     *
1078     * @see #getSendBufferSize()
1079     * @since 1.2
1080     */
1081    public synchronized void setSendBufferSize(int size)
1082    throws SocketException{
1083        if (!(size > 0)) {
1084            throw new IllegalArgumentException("negative send size");
1085        }
1086        if (isClosed())
1087            throw new SocketException("Socket is closed");
1088        getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
1089    }
1090
1091    /**
1092     * Get value of the SO_SNDBUF option for this <tt>Socket</tt>,
1093     * that is the buffer size used by the platform
1094     * for output on this <tt>Socket</tt>.
1095     * @return the value of the SO_SNDBUF option for this <tt>Socket</tt>.
1096     *
1097     * @exception SocketException if there is an error
1098     * in the underlying protocol, such as a TCP error.
1099     *
1100     * @see #setSendBufferSize(int)
1101     * @since 1.2
1102     */
1103    public synchronized int getSendBufferSize() throws SocketException {
1104        if (isClosed())
1105            throw new SocketException("Socket is closed");
1106        int result = 0;
1107        Object o = getImpl().getOption(SocketOptions.SO_SNDBUF);
1108        if (o instanceof Integer) {
1109            result = ((Integer)o).intValue();
1110        }
1111        return result;
1112    }
1113
1114    /**
1115     * Sets the SO_RCVBUF option to the specified value for this
1116     * <tt>Socket</tt>. The SO_RCVBUF option is used by the platform's
1117     * networking code as a hint for the size to set
1118     * the underlying network I/O buffers.
1119     *
1120     * <p>Increasing the receive buffer size can increase the performance of
1121     * network I/O for high-volume connection, while decreasing it can
1122     * help reduce the backlog of incoming data.
1123     *
1124     * <p>Because SO_RCVBUF is a hint, applications that want to
1125     * verify what size the buffers were set to should call
1126     * {@link #getReceiveBufferSize()}.
1127     *
1128     * <p>The value of SO_RCVBUF is also used to set the TCP receive window
1129     * that is advertized to the remote peer. Generally, the window size
1130     * can be modified at any time when a socket is connected. However, if
1131     * a receive window larger than 64K is required then this must be requested
1132     * <B>before</B> the socket is connected to the remote peer. There are two
1133     * cases to be aware of:<p>
1134     * <ol>
1135     * <li>For sockets accepted from a ServerSocket, this must be done by calling
1136     * {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket
1137     * is bound to a local address.<p></li>
1138     * <li>For client sockets, setReceiveBufferSize() must be called before
1139     * connecting the socket to its remote peer.<p></li></ol>
1140     * @param size the size to which to set the receive buffer
1141     * size. This value must be greater than 0.
1142     *
1143     * @exception IllegalArgumentException if the value is 0 or is
1144     * negative.
1145     *
1146     * @exception SocketException if there is an error
1147     * in the underlying protocol, such as a TCP error.
1148     *
1149     * @see #getReceiveBufferSize()
1150     * @see ServerSocket#setReceiveBufferSize(int)
1151     * @since 1.2
1152     */
1153    public synchronized void setReceiveBufferSize(int size)
1154    throws SocketException{
1155        if (size <= 0) {
1156            throw new IllegalArgumentException("invalid receive size");
1157        }
1158        if (isClosed())
1159            throw new SocketException("Socket is closed");
1160        getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
1161    }
1162
1163    /**
1164     * Gets the value of the SO_RCVBUF option for this <tt>Socket</tt>,
1165     * that is the buffer size used by the platform for
1166     * input on this <tt>Socket</tt>.
1167     *
1168     * @return the value of the SO_RCVBUF option for this <tt>Socket</tt>.
1169     * @exception SocketException if there is an error
1170     * in the underlying protocol, such as a TCP error.
1171     * @see #setReceiveBufferSize(int)
1172     * @since 1.2
1173     */
1174    public synchronized int getReceiveBufferSize()
1175    throws SocketException{
1176        if (isClosed())
1177            throw new SocketException("Socket is closed");
1178        int result = 0;
1179        Object o = getImpl().getOption(SocketOptions.SO_RCVBUF);
1180        if (o instanceof Integer) {
1181            result = ((Integer)o).intValue();
1182        }
1183        return result;
1184    }
1185
1186    /**
1187     * Enable/disable SO_KEEPALIVE.
1188     *
1189     * @param on     whether or not to have socket keep alive turned on.
1190     * @exception SocketException if there is an error
1191     * in the underlying protocol, such as a TCP error.
1192     * @since 1.3
1193     * @see #getKeepAlive()
1194     */
1195    public void setKeepAlive(boolean on) throws SocketException {
1196        if (isClosed())
1197            throw new SocketException("Socket is closed");
1198        getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
1199    }
1200
1201    /**
1202     * Tests if SO_KEEPALIVE is enabled.
1203     *
1204     * @return a <code>boolean</code> indicating whether or not SO_KEEPALIVE is enabled.
1205     * @exception SocketException if there is an error
1206     * in the underlying protocol, such as a TCP error.
1207     * @since   1.3
1208     * @see #setKeepAlive(boolean)
1209     */
1210    public boolean getKeepAlive() throws SocketException {
1211        if (isClosed())
1212            throw new SocketException("Socket is closed");
1213        return ((Boolean) getImpl().getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();
1214    }
1215
1216    /**
1217     * Sets traffic class or type-of-service octet in the IP
1218     * header for packets sent from this Socket.
1219     * As the underlying network implementation may ignore this
1220     * value applications should consider it a hint.
1221     *
1222     * <P> The tc <B>must</B> be in the range <code> 0 <= tc <=
1223     * 255</code> or an IllegalArgumentException will be thrown.
1224     * <p>Notes:
1225     * <p> For Internet Protocol v4 the value consists of an octet
1226     * with precedence and TOS fields as detailed in RFC 1349. The
1227     * TOS field is bitset created by bitwise-or'ing values such
1228     * the following :-
1229     * <p>
1230     * <UL>
1231     * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI>
1232     * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI>
1233     * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI>
1234     * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI>
1235     * </UL>
1236     * The last low order bit is always ignored as this
1237     * corresponds to the MBZ (must be zero) bit.
1238     * <p>
1239     * Setting bits in the precedence field may result in a
1240     * SocketException indicating that the operation is not
1241     * permitted.
1242     * <p>
1243     * As RFC 1122 section 4.2.4.2 indicates, a compliant TCP
1244     * implementation should, but is not required to, let application
1245     * change the TOS field during the lifetime of a connection.
1246     * So whether the type-of-service field can be changed after the
1247     * TCP connection has been established depends on the implementation
1248     * in the underlying platform. Applications should not assume that
1249     * they can change the TOS field after the connection.
1250     * <p>
1251     * For Internet Protocol v6 <code>tc</code> is the value that
1252     * would be placed into the sin6_flowinfo field of the IP header.
1253     *
1254     * @param tc        an <code>int</code> value for the bitset.
1255     * @throws SocketException if there is an error setting the
1256     * traffic class or type-of-service
1257     * @since 1.4
1258     * @see #getTrafficClass
1259     */
1260    public void setTrafficClass(int tc) throws SocketException {
1261        if (tc < 0 || tc > 255)
1262            throw new IllegalArgumentException("tc is not in range 0 -- 255");
1263
1264        if (isClosed())
1265            throw new SocketException("Socket is closed");
1266        getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
1267    }
1268
1269    /**
1270     * Gets traffic class or type-of-service in the IP header
1271     * for packets sent from this Socket
1272     * <p>
1273     * As the underlying network implementation may ignore the
1274     * traffic class or type-of-service set using {@link #setTrafficClass(int)}
1275     * this method may return a different value than was previously
1276     * set using the {@link #setTrafficClass(int)} method on this Socket.
1277     *
1278     * @return the traffic class or type-of-service already set
1279     * @throws SocketException if there is an error obtaining the
1280     * traffic class or type-of-service value.
1281     * @since 1.4
1282     * @see #setTrafficClass(int)
1283     */
1284    public int getTrafficClass() throws SocketException {
1285        return ((Integer) (getImpl().getOption(SocketOptions.IP_TOS))).intValue();

Large files files are truncated, but you can click here to view the full file