Source for java.net.Socket

   1: /* Socket.java -- Client socket implementation
   2:    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: package java.net;
  40: 
  41: import gnu.java.net.PlainSocketImpl;
  42: 
  43: import java.io.IOException;
  44: import java.io.InputStream;
  45: import java.io.OutputStream;
  46: import java.nio.channels.IllegalBlockingModeException;
  47: import java.nio.channels.SocketChannel;
  48: 
  49: 
  50: /* Written using on-line Java Platform 1.2 API Specification.
  51:  * Status:  I believe all methods are implemented.
  52:  */
  53: 
  54: /**
  55:  * This class models a client site socket.  A socket is a TCP/IP endpoint
  56:  * for network communications conceptually similar to a file handle.
  57:  * <p>
  58:  * This class does not actually do any work.  Instead, it redirects all of
  59:  * its calls to a socket implementation object which implements the
  60:  * <code>SocketImpl</code> interface.  The implementation class is
  61:  * instantiated by factory class that implements the
  62:  * <code>SocketImplFactory interface</code>.  A default
  63:  * factory is provided, however the factory may be set by a call to
  64:  * the <code>setSocketImplFactory</code> method.  Note that this may only be
  65:  * done once per virtual machine.  If a subsequent attempt is made to set the
  66:  * factory, a <code>SocketException</code> will be thrown.
  67:  *
  68:  * @author Aaron M. Renn (arenn@urbanophile.com)
  69:  * @author Per Bothner (bothner@cygnus.com)
  70:  */
  71: public class Socket
  72: {
  73:   /**
  74:    * This is the user SocketImplFactory for this class.  If this variable is
  75:    * null, a default factory is used.
  76:    */
  77:   static SocketImplFactory factory;
  78: 
  79:   /**
  80:    * The implementation object to which calls are redirected
  81:    */
  82:   // package-private because ServerSocket.implAccept() needs to access it.
  83:   SocketImpl impl;
  84: 
  85:   /**
  86:    * True if impl.create() has been called.
  87:    */
  88:   // package-private because ServerSocket.implAccept() needs to access it.
  89:   boolean implCreated;
  90: 
  91:   /**
  92:    * True if the socket is bound.
  93:    * Package private so it can be set from ServerSocket when accept is called.
  94:    */
  95:   boolean bound;
  96: 
  97:   /**
  98:    * True if input is shutdown.
  99:    */
 100:   private boolean inputShutdown;
 101: 
 102:   /**
 103:    * True if output is shutdown.
 104:    */
 105:   private boolean outputShutdown;
 106: 
 107:   /**
 108:    * Initializes a new instance of <code>Socket</code> object without
 109:    * connecting to a remote host.  This useful for subclasses of socket that
 110:    * might want this behavior.
 111:    *
 112:    * @specnote This constructor is public since JDK 1.4
 113:    * @since 1.1
 114:    */
 115:   public Socket()
 116:   {
 117:     if (factory != null)
 118:       impl = factory.createSocketImpl();
 119:     else
 120:       impl = new PlainSocketImpl();
 121:   }
 122: 
 123:   /**
 124:    * Initializes a new instance of <code>Socket</code> object without
 125:    * connecting to a remote host.  This is useful for subclasses of socket
 126:    * that might want this behavior.
 127:    * <p>
 128:    * Additionally, this socket will be created using the supplied
 129:    * implementation class instead the default class or one returned by a
 130:    * factory.  If this value is <code>null</code>, the default Socket
 131:    * implementation is used.
 132:    *
 133:    * @param impl The <code>SocketImpl</code> to use for this
 134:    *             <code>Socket</code>
 135:    *
 136:    * @exception SocketException If an error occurs
 137:    *
 138:    * @since 1.1
 139:    */
 140:   protected Socket(SocketImpl impl) throws SocketException
 141:   {
 142:     if (impl == null)
 143:       this.impl = new PlainSocketImpl();
 144:     else
 145:       this.impl = impl;
 146:   }
 147: 
 148:   /**
 149:    * Initializes a new instance of <code>Socket</code> and connects to the
 150:    * hostname and port specified as arguments.
 151:    *
 152:    * @param host The name of the host to connect to
 153:    * @param port The port number to connect to
 154:    *
 155:    * @exception UnknownHostException If the hostname cannot be resolved to a
 156:    * network address.
 157:    * @exception IOException If an error occurs
 158:    * @exception SecurityException If a security manager exists and its
 159:    * checkConnect method doesn't allow the operation
 160:    */
 161:   public Socket(String host, int port)
 162:     throws UnknownHostException, IOException
 163:   {
 164:     this(InetAddress.getByName(host), port, null, 0, true);
 165:   }
 166: 
 167:   /**
 168:    * Initializes a new instance of <code>Socket</code> and connects to the
 169:    * address and port number specified as arguments.
 170:    *
 171:    * @param address The address to connect to
 172:    * @param port The port number to connect to
 173:    *
 174:    * @exception IOException If an error occurs
 175:    * @exception SecurityException If a security manager exists and its
 176:    * checkConnect method doesn't allow the operation
 177:    */
 178:   public Socket(InetAddress address, int port) throws IOException
 179:   {
 180:     this(address, port, null, 0, true);
 181:   }
 182: 
 183:   /**
 184:    * Initializes a new instance of <code>Socket</code> that connects to the
 185:    * named host on the specified port and binds to the specified local address
 186:    * and port.
 187:    *
 188:    * @param host The name of the remote host to connect to.
 189:    * @param port The remote port to connect to.
 190:    * @param localAddr The local address to bind to.
 191:    * @param localPort The local port to bind to.
 192:    *
 193:    * @exception SecurityException If the <code>SecurityManager</code>
 194:    * exists and does not allow a connection to the specified host/port or
 195:    * binding to the specified local host/port.
 196:    * @exception IOException If a connection error occurs.
 197:    *
 198:    * @since 1.1
 199:    */
 200:   public Socket(String host, int port, InetAddress localAddr, int localPort)
 201:     throws IOException
 202:   {
 203:     this(InetAddress.getByName(host), port, localAddr, localPort, true);
 204:   }
 205: 
 206:   /**
 207:    * Initializes a new instance of <code>Socket</code> and connects to the
 208:    * address and port number specified as arguments, plus binds to the
 209:    * specified local address and port.
 210:    *
 211:    * @param address The remote address to connect to
 212:    * @param port The remote port to connect to
 213:    * @param localAddr The local address to connect to
 214:    * @param localPort The local port to connect to
 215:    *
 216:    * @exception IOException If an error occurs
 217:    * @exception SecurityException If a security manager exists and its
 218:    * checkConnect method doesn't allow the operation
 219:    *
 220:    * @since 1.1
 221:    */
 222:   public Socket(InetAddress address, int port, InetAddress localAddr,
 223:                 int localPort) throws IOException
 224:   {
 225:     this(address, port, localAddr, localPort, true);
 226:   }
 227: 
 228:   /**
 229:    * Initializes a new instance of <code>Socket</code> and connects to the
 230:    * hostname and port specified as arguments.  If the stream argument is set
 231:    * to <code>true</code>, then a stream socket is created.  If it is
 232:    * <code>false</code>, a datagram socket is created.
 233:    *
 234:    * @param host The name of the host to connect to
 235:    * @param port The port to connect to
 236:    * @param stream <code>true</code> for a stream socket, <code>false</code>
 237:    * for a datagram socket
 238:    *
 239:    * @exception IOException If an error occurs
 240:    * @exception SecurityException If a security manager exists and its
 241:    * checkConnect method doesn't allow the operation
 242:    *
 243:    * @deprecated Use the <code>DatagramSocket</code> class to create
 244:    * datagram oriented sockets.
 245:    */
 246:   public Socket(String host, int port, boolean stream)
 247:     throws IOException
 248:   {
 249:     this(InetAddress.getByName(host), port, null, 0, stream);
 250:   }
 251: 
 252:   /**
 253:    * Initializes a new instance of <code>Socket</code> and connects to the
 254:    * address and port number specified as arguments.  If the stream param is
 255:    * <code>true</code>, a stream socket will be created, otherwise a datagram
 256:    * socket is created.
 257:    *
 258:    * @param host The address to connect to
 259:    * @param port The port number to connect to
 260:    * @param stream <code>true</code> to create a stream socket,
 261:    * <code>false</code> to create a datagram socket.
 262:    *
 263:    * @exception IOException If an error occurs
 264:    * @exception SecurityException If a security manager exists and its
 265:    * checkConnect method doesn't allow the operation
 266:    *
 267:    * @deprecated Use the <code>DatagramSocket</code> class to create
 268:    * datagram oriented sockets.
 269:    */
 270:   public Socket(InetAddress host, int port, boolean stream)
 271:     throws IOException
 272:   {
 273:     this(host, port, null, 0, stream);
 274:   }
 275: 
 276:   /**
 277:    * This constructor is where the real work takes place.  Connect to the
 278:    * specified address and port.  Use default local values if not specified,
 279:    * otherwise use the local host and port passed in.  Create as stream or
 280:    * datagram based on "stream" argument.
 281:    * <p>
 282:    *
 283:    * @param raddr The remote address to connect to
 284:    * @param rport The remote port to connect to
 285:    * @param laddr The local address to connect to
 286:    * @param lport The local port to connect to
 287:    * @param stream true for a stream socket, false for a datagram socket
 288:    *
 289:    * @exception IOException If an error occurs
 290:    * @exception SecurityException If a security manager exists and its
 291:    * checkConnect method doesn't allow the operation
 292:    */
 293:   private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
 294:                  boolean stream) throws IOException
 295:   {
 296:     this();
 297: 
 298:     SecurityManager sm = System.getSecurityManager();
 299:     if (sm != null)
 300:       sm.checkConnect(raddr.getHostAddress(), rport);
 301: 
 302:     // bind socket
 303:     SocketAddress bindaddr =
 304:       laddr == null ? null : new InetSocketAddress(laddr, lport);
 305:     bind(bindaddr);
 306: 
 307:     // Connect socket in case of Exceptions we must close the socket
 308:     // because an exception in the constructor means that the caller will
 309:     // not have a reference to this instance.
 310:     // Note: You may have the idea that the exception treatment
 311:     // should be moved into connect() but there is a Mauve test which
 312:     // shows that a failed connect should not close the socket.
 313:     try
 314:       {
 315:         connect(new InetSocketAddress(raddr, rport));
 316:       }
 317:     catch (IOException ioe)
 318:       {
 319:         impl.close();
 320:         throw ioe;
 321:       }
 322:     catch (RuntimeException re)
 323:       {
 324:         impl.close();
 325:         throw re;
 326:       }
 327: 
 328:     // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
 329:     // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
 330:     // that default.  JDK 1.2 doc infers not to do a bind.
 331:   }
 332: 
 333:   private SocketImpl getImpl() throws SocketException
 334:   {
 335:     if (! implCreated)
 336:       {
 337:         try
 338:           {
 339:             impl.create(true);
 340:           }
 341:         catch (IOException x)
 342:           {
 343:             throw (SocketException) new SocketException().initCause(x);
 344:           }
 345:         implCreated = true;
 346:       }
 347:     return impl;
 348:   }
 349: 
 350:   /**
 351:    * Binds the socket to the given local address/port
 352:    *
 353:    * @param bindpoint The address/port to bind to
 354:    *
 355:    * @exception IOException If an error occurs
 356:    * @exception SecurityException If a security manager exists and its
 357:    * checkConnect method doesn't allow the operation
 358:    * @exception IllegalArgumentException If the address type is not supported
 359:    *
 360:    * @since 1.4
 361:    */
 362:   public void bind(SocketAddress bindpoint) throws IOException
 363:   {
 364:     if (isClosed())
 365:       throw new SocketException("socket is closed");
 366: 
 367:     // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
 368:     // socket will be bound to an ephemeral port and a valid local address.
 369:     if (bindpoint == null)
 370:       bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
 371: 
 372:     if (! (bindpoint instanceof InetSocketAddress))
 373:       throw new IllegalArgumentException();
 374: 
 375:     InetSocketAddress tmp = (InetSocketAddress) bindpoint;
 376: 
 377:     // bind to address/port
 378:     try
 379:       {
 380:     getImpl().bind(tmp.getAddress(), tmp.getPort());
 381:     bound = true;
 382:       }
 383:     catch (IOException exception)
 384:       {
 385:     close();
 386:     throw exception;
 387:       }
 388:     catch (RuntimeException exception)
 389:       {
 390:     close();
 391:     throw exception;
 392:       }
 393:     catch (Error error)
 394:       {
 395:     close();
 396:     throw error;
 397:       }
 398:   }
 399: 
 400:   /**
 401:    * Connects the socket with a remote address.
 402:    *
 403:    * @param endpoint The address to connect to
 404:    *
 405:    * @exception IOException If an error occurs
 406:    * @exception IllegalArgumentException If the addess type is not supported
 407:    * @exception IllegalBlockingModeException If this socket has an associated
 408:    * channel, and the channel is in non-blocking mode
 409:    *
 410:    * @since 1.4
 411:    */
 412:   public void connect(SocketAddress endpoint) throws IOException
 413:   {
 414:     connect(endpoint, 0);
 415:   }
 416: 
 417:   /**
 418:    * Connects the socket with a remote address. A timeout of zero is
 419:    * interpreted as an infinite timeout. The connection will then block
 420:    * until established or an error occurs.
 421:    *
 422:    * @param endpoint The address to connect to
 423:    * @param timeout The length of the timeout in milliseconds, or
 424:    * 0 to indicate no timeout.
 425:    *
 426:    * @exception IOException If an error occurs
 427:    * @exception IllegalArgumentException If the address type is not supported
 428:    * @exception IllegalBlockingModeException If this socket has an associated
 429:    * channel, and the channel is in non-blocking mode
 430:    * @exception SocketTimeoutException If the timeout is reached
 431:    *
 432:    * @since 1.4
 433:    */
 434:   public void connect(SocketAddress endpoint, int timeout)
 435:     throws IOException
 436:   {
 437:     if (isClosed())
 438:       throw new SocketException("socket is closed");
 439: 
 440:     if (! (endpoint instanceof InetSocketAddress))
 441:       throw new IllegalArgumentException("unsupported address type");
 442: 
 443:     // The Sun spec says that if we have an associated channel and
 444:     // it is in non-blocking mode, we throw an IllegalBlockingModeException.
 445:     // However, in our implementation if the channel itself initiated this
 446:     // operation, then we must honor it regardless of its blocking mode.
 447:     if (getChannel() != null && ! getChannel().isBlocking()
 448:         && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
 449:       throw new IllegalBlockingModeException();
 450: 
 451:     if (! isBound())
 452:       bind(null);
 453: 
 454:     getImpl().connect(endpoint, timeout);
 455:   }
 456: 
 457:   /**
 458:    * Returns the address of the remote end of the socket.  If this socket
 459:    * is not connected, then <code>null</code> is returned.
 460:    *
 461:    * @return The remote address this socket is connected to
 462:    */
 463:   public InetAddress getInetAddress()
 464:   {
 465:     if (! isConnected())
 466:       return null;
 467: 
 468:     try
 469:       {
 470:     return getImpl().getInetAddress();
 471:       }
 472:     catch (SocketException e)
 473:       {
 474:     // This cannot happen as we are connected.
 475:       }
 476: 
 477:     return null;
 478:   }
 479: 
 480:   /**
 481:    * Returns the local address to which this socket is bound.  If this socket
 482:    * is not connected, then a wildcard address, for which
 483:    * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
 484:    *
 485:    * @return The local address
 486:    *
 487:    * @since 1.1
 488:    */
 489:   public InetAddress getLocalAddress()
 490:   {
 491:     if (! isBound())
 492:       return InetAddress.ANY_IF;
 493: 
 494:     InetAddress addr = null;
 495: 
 496:     if (impl instanceof PlainSocketImpl)
 497:       addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();
 498:     
 499:     if (addr == null)
 500:       {
 501:         try
 502:           {
 503:             addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
 504:           }
 505:         catch (SocketException e)
 506:           {
 507:             // (hopefully) shouldn't happen
 508:             // throw new java.lang.InternalError
 509:             //      ("Error in PlainSocketImpl.getOption");
 510:             return null;
 511:           }
 512:       }
 513: 
 514:     // FIXME: According to libgcj, checkConnect() is supposed to be called
 515:     // before performing this operation.  Problems: 1) We don't have the
 516:     // addr until after we do it, so we do a post check.  2). The docs I
 517:     // see don't require this in the Socket case, only DatagramSocket, but
 518:     // we'll assume they mean both.
 519:     SecurityManager sm = System.getSecurityManager();
 520:     if (sm != null)
 521:       sm.checkConnect(addr.getHostName(), getLocalPort());
 522: 
 523:     return addr;
 524:   }
 525: 
 526:   /**
 527:    * Returns the port number of the remote end of the socket connection.  If
 528:    * this socket is not connected, then 0 is returned.
 529:    *
 530:    * @return The remote port this socket is connected to
 531:    */
 532:   public int getPort()
 533:   {
 534:     if (! isConnected())
 535:       return 0;
 536: 
 537:     try
 538:       {
 539:     return getImpl().getPort();
 540:       }
 541:     catch (SocketException e)
 542:       {
 543:     // This cannot happen as we are connected.
 544:       }
 545: 
 546:     return 0;
 547:   }
 548: 
 549:   /**
 550:    * Returns the local port number to which this socket is bound.  If this
 551:    * socket is not connected, then -1 is returned.
 552:    *
 553:    * @return The local port
 554:    */
 555:   public int getLocalPort()
 556:   {
 557:     if (! isBound())
 558:       return -1;
 559: 
 560:     try
 561:       {
 562:     if (getImpl() != null)
 563:       return getImpl().getLocalPort();
 564:       }
 565:     catch (SocketException e)
 566:       {
 567:     // This cannot happen as we are bound.
 568:       }
 569: 
 570:     return -1;
 571:   }
 572: 
 573:   /**
 574:    * Returns local socket address.
 575:    *
 576:    * @return the local socket address, null if not bound
 577:    *
 578:    * @since 1.4
 579:    */
 580:   public SocketAddress getLocalSocketAddress()
 581:   {
 582:     if (! isBound())
 583:       return null;
 584: 
 585:     InetAddress addr = getLocalAddress();
 586: 
 587:     try
 588:       {
 589:     return new InetSocketAddress(addr, getImpl().getLocalPort());
 590:       }
 591:     catch (SocketException e)
 592:       {
 593:     // This cannot happen as we are bound.
 594:     return null;
 595:       }
 596:   }
 597: 
 598:   /**
 599:    * Returns the remote socket address.
 600:    *
 601:    * @return the remote socket address, null of not connected
 602:    *
 603:    * @since 1.4
 604:    */
 605:   public SocketAddress getRemoteSocketAddress()
 606:   {
 607:     if (! isConnected())
 608:       return null;
 609: 
 610:     try
 611:       {
 612:     return new InetSocketAddress(getImpl().getInetAddress(),
 613:                                  getImpl().getPort());
 614:       }
 615:     catch (SocketException e)
 616:       {
 617:     // This cannot happen as we are connected.
 618:     return null;
 619:       }
 620:   }
 621: 
 622:   /**
 623:    * Returns an InputStream for reading from this socket.
 624:    *
 625:    * @return The InputStream object
 626:    *
 627:    * @exception IOException If an error occurs or Socket is not connected
 628:    */
 629:   public InputStream getInputStream() throws IOException
 630:   {
 631:     if (isClosed())
 632:       throw new SocketException("socket is closed");
 633: 
 634:     if (! isConnected())
 635:       throw new IOException("not connected");
 636: 
 637:     return getImpl().getInputStream();
 638:   }
 639: 
 640:   /**
 641:    * Returns an OutputStream for writing to this socket.
 642:    *
 643:    * @return The OutputStream object
 644:    *
 645:    * @exception IOException If an error occurs or Socket is not connected
 646:    */
 647:   public OutputStream getOutputStream() throws IOException
 648:   {
 649:     if (isClosed())
 650:       throw new SocketException("socket is closed");
 651: 
 652:     if (! isConnected())
 653:       throw new IOException("not connected");
 654: 
 655:     return getImpl().getOutputStream();
 656:   }
 657: 
 658:   /**
 659:    * Sets the TCP_NODELAY option on the socket.
 660:    *
 661:    * @param on true to enable, false to disable
 662:    *
 663:    * @exception SocketException If an error occurs or Socket is not connected
 664:    *
 665:    * @since 1.1
 666:    */
 667:   public void setTcpNoDelay(boolean on) throws SocketException
 668:   {
 669:     if (isClosed())
 670:       throw new SocketException("socket is closed");
 671: 
 672:     getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
 673:   }
 674: 
 675:   /**
 676:    * Tests whether or not the TCP_NODELAY option is set on the socket.
 677:    * Returns true if enabled, false if disabled. When on it disables the
 678:    * Nagle algorithm which means that packets are always send immediatly and
 679:    * never merged together to reduce network trafic.
 680:    *
 681:    * @return Whether or not TCP_NODELAY is set
 682:    *
 683:    * @exception SocketException If an error occurs or Socket not connected
 684:    *
 685:    * @since 1.1
 686:    */
 687:   public boolean getTcpNoDelay() throws SocketException
 688:   {
 689:     if (isClosed())
 690:       throw new SocketException("socket is closed");
 691: 
 692:     Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
 693: 
 694:     if (on instanceof Boolean)
 695:       return (((Boolean) on).booleanValue());
 696:     else
 697:       throw new SocketException("Internal Error");
 698:   }
 699: 
 700:   /**
 701:    * Sets the value of the SO_LINGER option on the socket.  If the
 702:    * SO_LINGER option is set on a socket and there is still data waiting to
 703:    * be sent when the socket is closed, then the close operation will block
 704:    * until either that data is delivered or until the timeout period
 705:    * expires.  The linger interval is specified in hundreths of a second
 706:    * (platform specific?)
 707:    *
 708:    * @param on true to enable SO_LINGER, false to disable
 709:    * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
 710:    * SO_LINGER not set.
 711:    *
 712:    * @exception SocketException If an error occurs or Socket not connected
 713:    * @exception IllegalArgumentException If linger is negative
 714:    *
 715:    * @since 1.1
 716:    */
 717:   public void setSoLinger(boolean on, int linger) throws SocketException
 718:   {
 719:     if (isClosed())
 720:       throw new SocketException("socket is closed");
 721: 
 722:     if (on)
 723:       {
 724:     if (linger < 0)
 725:       throw new IllegalArgumentException("SO_LINGER must be >= 0");
 726: 
 727:     if (linger > 65535)
 728:       linger = 65535;
 729: 
 730:     getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
 731:       }
 732:     else
 733:       getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
 734:   }
 735: 
 736:   /**
 737:    * Returns the value of the SO_LINGER option on the socket.  If the
 738:    * SO_LINGER option is set on a socket and there is still data waiting to
 739:    * be sent when the socket is closed, then the close operation will block
 740:    * until either that data is delivered or until the timeout period
 741:    * expires.  This method either returns the timeouts (in hundredths of
 742:    * of a second (platform specific?)) if SO_LINGER is set, or -1 if
 743:    * SO_LINGER is not set.
 744:    *
 745:    * @return The SO_LINGER timeout in hundreths of a second or -1
 746:    * if SO_LINGER not set
 747:    *
 748:    * @exception SocketException If an error occurs or Socket is not connected
 749:    *
 750:    * @since 1.1
 751:    */
 752:   public int getSoLinger() throws SocketException
 753:   {
 754:     if (isClosed())
 755:       throw new SocketException("socket is closed");
 756: 
 757:     Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
 758: 
 759:     if (linger instanceof Integer)
 760:       return (((Integer) linger).intValue());
 761:     else
 762:       return -1;
 763:   }
 764: 
 765:   /**
 766:    * Sends urgent data through the socket
 767:    *
 768:    * @param data The data to send.
 769:    * Only the lowest eight bits of data are sent
 770:    *
 771:    * @exception IOException If an error occurs
 772:    *
 773:    * @since 1.4
 774:    */
 775:   public void sendUrgentData(int data) throws IOException
 776:   {
 777:     if (isClosed())
 778:       throw new SocketException("socket is closed");
 779: 
 780:     getImpl().sendUrgentData(data);
 781:   }
 782: 
 783:   /**
 784:    * Enables/disables the SO_OOBINLINE option
 785:    *
 786:    * @param on True if SO_OOBLINE should be enabled
 787:    *
 788:    * @exception SocketException If an error occurs
 789:    *
 790:    * @since 1.4
 791:    */
 792:   public void setOOBInline(boolean on) throws SocketException
 793:   {
 794:     if (isClosed())
 795:       throw new SocketException("socket is closed");
 796: 
 797:     getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
 798:   }
 799: 
 800:   /**
 801:    * Returns the current setting of the SO_OOBINLINE option for this socket
 802:    *
 803:    * @return True if SO_OOBINLINE is set, false otherwise.
 804:    *
 805:    * @exception SocketException If an error occurs
 806:    *
 807:    * @since 1.4
 808:    */
 809:   public boolean getOOBInline() throws SocketException
 810:   {
 811:     if (isClosed())
 812:       throw new SocketException("socket is closed");
 813: 
 814:     Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
 815: 
 816:     if (buf instanceof Boolean)
 817:       return (((Boolean) buf).booleanValue());
 818:     else
 819:       throw new SocketException("Internal Error: Unexpected type");
 820:   }
 821: 
 822:   /**
 823:    * Sets the value of the SO_TIMEOUT option on the socket.  If this value
 824:    * is set, and an read/write is performed that does not complete within
 825:    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
 826:    * would be sent in Unix if no data had been read).  A value of 0 for
 827:    * this option implies that there is no timeout (ie, operations will
 828:    * block forever).  On systems that have separate read and write timeout
 829:    * values, this method returns the read timeout.  This
 830:    * value is in milliseconds.
 831:    *
 832:    * @param timeout The length of the timeout in milliseconds, or
 833:    * 0 to indicate no timeout.
 834:    *
 835:    * @exception SocketException If an error occurs or Socket not connected
 836:    *
 837:    * @since 1.1
 838:    */
 839:   public synchronized void setSoTimeout(int timeout) throws SocketException
 840:   {
 841:     if (isClosed())
 842:       throw new SocketException("socket is closed");
 843: 
 844:     if (timeout < 0)
 845:       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
 846: 
 847:     getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
 848:   }
 849: 
 850:   /**
 851:    * Returns the value of the SO_TIMEOUT option on the socket.  If this value
 852:    * is set, and an read/write is performed that does not complete within
 853:    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
 854:    * would be sent in Unix if no data had been read).  A value of 0 for
 855:    * this option implies that there is no timeout (ie, operations will
 856:    * block forever).  On systems that have separate read and write timeout
 857:    * values, this method returns the read timeout.  This
 858:    * value is in thousandths of a second (implementation specific?).
 859:    *
 860:    * @return The length of the timeout in thousandth's of a second or 0
 861:    * if not set
 862:    *
 863:    * @exception SocketException If an error occurs or Socket not connected
 864:    *
 865:    * @since 1.1
 866:    */
 867:   public synchronized int getSoTimeout() throws SocketException
 868:   {
 869:     if (isClosed())
 870:       throw new SocketException("socket is closed");
 871: 
 872:     Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
 873:     if (timeout instanceof Integer)
 874:       return (((Integer) timeout).intValue());
 875:     else
 876:       return 0;
 877:   }
 878: 
 879:   /**
 880:    * This method sets the value for the system level socket option
 881:    * SO_SNDBUF to the specified value.  Note that valid values for this
 882:    * option are specific to a given operating system.
 883:    *
 884:    * @param size The new send buffer size.
 885:    *
 886:    * @exception SocketException If an error occurs or Socket not connected
 887:    * @exception IllegalArgumentException If size is 0 or negative
 888:    *
 889:    * @since 1.2
 890:    */
 891:   public void setSendBufferSize(int size) throws SocketException
 892:   {
 893:     if (isClosed())
 894:       throw new SocketException("socket is closed");
 895: 
 896:     if (size <= 0)
 897:       throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
 898: 
 899:     getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
 900:   }
 901: 
 902:   /**
 903:    * This method returns the value of the system level socket option
 904:    * SO_SNDBUF, which is used by the operating system to tune buffer
 905:    * sizes for data transfers.
 906:    *
 907:    * @return The send buffer size.
 908:    *
 909:    * @exception SocketException If an error occurs or socket not connected
 910:    *
 911:    * @since 1.2
 912:    */
 913:   public int getSendBufferSize() throws SocketException
 914:   {
 915:     if (isClosed())
 916:       throw new SocketException("socket is closed");
 917: 
 918:     Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
 919: 
 920:     if (buf instanceof Integer)
 921:       return (((Integer) buf).intValue());
 922:     else
 923:       throw new SocketException("Internal Error: Unexpected type");
 924:   }
 925: 
 926:   /**
 927:    * This method sets the value for the system level socket option
 928:    * SO_RCVBUF to the specified value.  Note that valid values for this
 929:    * option are specific to a given operating system.
 930:    *
 931:    * @param size The new receive buffer size.
 932:    *
 933:    * @exception SocketException If an error occurs or Socket is not connected
 934:    * @exception IllegalArgumentException If size is 0 or negative
 935:    *
 936:    * @since 1.2
 937:    */
 938:   public void setReceiveBufferSize(int size) throws SocketException
 939:   {
 940:     if (isClosed())
 941:       throw new SocketException("socket is closed");
 942: 
 943:     if (size <= 0)
 944:       throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
 945: 
 946:     getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
 947:   }
 948: 
 949:   /**
 950:    * This method returns the value of the system level socket option
 951:    * SO_RCVBUF, which is used by the operating system to tune buffer
 952:    * sizes for data transfers.
 953:    *
 954:    * @return The receive buffer size.
 955:    *
 956:    * @exception SocketException If an error occurs or Socket is not connected
 957:    *
 958:    * @since 1.2
 959:    */
 960:   public int getReceiveBufferSize() throws SocketException
 961:   {
 962:     if (isClosed())
 963:       throw new SocketException("socket is closed");
 964: 
 965:     Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
 966: 
 967:     if (buf instanceof Integer)
 968:       return (((Integer) buf).intValue());
 969:     else
 970:       throw new SocketException("Internal Error: Unexpected type");
 971:   }
 972: 
 973:   /**
 974:    * This method sets the value for the socket level socket option
 975:    * SO_KEEPALIVE.
 976:    *
 977:    * @param on True if SO_KEEPALIVE should be enabled
 978:    *
 979:    * @exception SocketException If an error occurs or Socket is not connected
 980:    *
 981:    * @since 1.3
 982:    */
 983:   public void setKeepAlive(boolean on) throws SocketException
 984:   {
 985:     if (isClosed())
 986:       throw new SocketException("socket is closed");
 987: 
 988:     getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
 989:   }
 990: 
 991:   /**
 992:    * This method returns the value of the socket level socket option
 993:    * SO_KEEPALIVE.
 994:    *
 995:    * @return The setting
 996:    *
 997:    * @exception SocketException If an error occurs or Socket is not connected
 998:    *
 999:    * @since 1.3
1000:    */
1001:   public boolean getKeepAlive() throws SocketException
1002:   {
1003:     if (isClosed())
1004:       throw new SocketException("socket is closed");
1005: 
1006:     Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
1007: 
1008:     if (buf instanceof Boolean)
1009:       return (((Boolean) buf).booleanValue());
1010:     else
1011:       throw new SocketException("Internal Error: Unexpected type");
1012:   }
1013: 
1014:   /**
1015:    * Closes the socket.
1016:    *
1017:    * @exception IOException If an error occurs
1018:    */
1019:   public synchronized void close() throws IOException
1020:   {
1021:     if (isClosed())
1022:       return;
1023: 
1024:     impl.close();
1025:     impl = null;
1026:   }
1027: 
1028:   /**
1029:    * Converts this <code>Socket</code> to a <code>String</code>.
1030:    *
1031:    * @return The <code>String</code> representation of this <code>Socket</code>
1032:    */
1033:   public String toString()
1034:   {
1035:     try
1036:       {
1037:     if (isConnected())
1038:       return (super.toString()
1039:                   + " [addr=" + getImpl().getInetAddress() + ",port="
1040:               + getImpl().getPort() + ",localport="
1041:               + getImpl().getLocalPort() + "]");
1042:       }
1043:     catch (SocketException e)
1044:       {
1045:     // This cannot happen as we are connected.
1046:       }
1047: 
1048:     return super.toString() + " [unconnected]";
1049:   }
1050: 
1051:   /**
1052:    * Sets the <code>SocketImplFactory</code>.  This may be done only once per
1053:    * virtual machine.  Subsequent attempts will generate a
1054:    * <code>SocketException</code>.  Note that a <code>SecurityManager</code>
1055:    * check is made prior to setting the factory.  If
1056:    * insufficient privileges exist to set the factory, then an
1057:    * <code>IOException</code> will be thrown.
1058:    *
1059:    * @param fac the factory to set
1060:    *
1061:    * @exception SecurityException If the <code>SecurityManager</code> does
1062:    * not allow this operation.
1063:    * @exception SocketException If the SocketImplFactory is already defined
1064:    * @exception IOException If any other error occurs
1065:    */
1066:   public static synchronized void setSocketImplFactory(SocketImplFactory fac)
1067:     throws IOException
1068:   {
1069:     // See if already set
1070:     if (factory != null)
1071:       throw new SocketException("SocketImplFactory already defined");
1072: 
1073:     // Check permissions
1074:     SecurityManager sm = System.getSecurityManager();
1075:     if (sm != null)
1076:       sm.checkSetFactory();
1077: 
1078:     if (fac == null)
1079:       throw new SocketException("SocketImplFactory cannot be null");
1080: 
1081:     factory = fac;
1082:   }
1083: 
1084:   /**
1085:    * Closes the input side of the socket stream.
1086:    *
1087:    * @exception IOException If an error occurs.
1088:    *
1089:    * @since 1.3
1090:    */
1091:   public void shutdownInput() throws IOException
1092:   {
1093:     if (isClosed())
1094:       throw new SocketException("socket is closed");
1095: 
1096:     getImpl().shutdownInput();
1097:     inputShutdown = true;
1098:   }
1099: 
1100:   /**
1101:    * Closes the output side of the socket stream.
1102:    *
1103:    * @exception IOException If an error occurs.
1104:    *
1105:    * @since 1.3
1106:    */
1107:   public void shutdownOutput() throws IOException
1108:   {
1109:     if (isClosed())
1110:       throw new SocketException("socket is closed");
1111: 
1112:     getImpl().shutdownOutput();
1113:     outputShutdown = true;
1114:   }
1115: 
1116:   /**
1117:    * Returns the socket channel associated with this socket.
1118:    *
1119:    * @return the associated socket channel,
1120:    * null if no associated channel exists
1121:    *
1122:    * @since 1.4
1123:    */
1124:   public SocketChannel getChannel()
1125:   {
1126:     return null;
1127:   }
1128: 
1129:   /**
1130:    * Checks if the SO_REUSEADDR option is enabled
1131:    *
1132:    * @return True if SO_REUSEADDR is set, false otherwise.
1133:    *
1134:    * @exception SocketException If an error occurs
1135:    *
1136:    * @since 1.4
1137:    */
1138:   public boolean getReuseAddress() throws SocketException
1139:   {
1140:     if (isClosed())
1141:       throw new SocketException("socket is closed");
1142: 
1143:     Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1144: 
1145:     if (! (reuseaddr instanceof Boolean))
1146:       throw new SocketException("Internal Error");
1147: 
1148:     return ((Boolean) reuseaddr).booleanValue();
1149:   }
1150: 
1151:   /**
1152:    * Enables/Disables the SO_REUSEADDR option
1153:    *
1154:    * @param reuseAddress true if SO_REUSEADDR should be enabled,
1155:    * false otherwise
1156:    *
1157:    * @exception SocketException If an error occurs
1158:    *
1159:    * @since 1.4
1160:    */
1161:   public void setReuseAddress(boolean reuseAddress) throws SocketException
1162:   {
1163:     if (isClosed())
1164:       throw new SocketException("socket is closed");
1165: 
1166:     getImpl().setOption(SocketOptions.SO_REUSEADDR,
1167:                         Boolean.valueOf(reuseAddress));
1168:   }
1169: 
1170:   /**
1171:    * Returns the current traffic class
1172:    *
1173:    * @return The current traffic class.
1174:    *
1175:    * @exception SocketException If an error occurs
1176:    *
1177:    * @see Socket#setTrafficClass(int tc)
1178:    *
1179:    * @since 1.4
1180:    */
1181:   public int getTrafficClass() throws SocketException
1182:   {
1183:     if (isClosed())
1184:       throw new SocketException("socket is closed");
1185: 
1186:     Object obj = getImpl().getOption(SocketOptions.IP_TOS);
1187: 
1188:     if (obj instanceof Integer)
1189:       return ((Integer) obj).intValue();
1190:     else
1191:       throw new SocketException("Unexpected type");
1192:   }
1193: 
1194:   /**
1195:    * Sets the traffic class value
1196:    *
1197:    * @param tc The traffic class
1198:    *
1199:    * @exception SocketException If an error occurs
1200:    * @exception IllegalArgumentException If tc value is illegal
1201:    *
1202:    * @see Socket#getTrafficClass()
1203:    *
1204:    * @since 1.4
1205:    */
1206:   public void setTrafficClass(int tc) throws SocketException
1207:   {
1208:     if (isClosed())
1209:       throw new SocketException("socket is closed");
1210: 
1211:     if (tc < 0 || tc > 255)
1212:       throw new IllegalArgumentException();
1213: 
1214:     getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
1215:   }
1216: 
1217:   /**
1218:    * Checks if the socket is connected
1219:    *
1220:    * @return True if socket is connected, false otherwise.
1221:    *
1222:    * @since 1.4
1223:    */
1224:   public boolean isConnected()
1225:   {
1226:     if (impl == null)
1227:       return false;
1228:     
1229:     return impl.getInetAddress() != null;
1230:   }
1231: 
1232:   /**
1233:    * Checks if the socket is already bound.
1234:    *
1235:    * @return True if socket is bound, false otherwise.
1236:    *
1237:    * @since 1.4
1238:    */
1239:   public boolean isBound()
1240:   {
1241:     if (isClosed())
1242:       return false;
1243:     if (impl instanceof PlainSocketImpl)
1244:       {
1245:         InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress(); 
1246:         return addr != null && addr.getAddress() != null;
1247:       }
1248:     return bound;
1249:   }
1250: 
1251:   /**
1252:    * Checks if the socket is closed.
1253:    *
1254:    * @return True if socket is closed, false otherwise.
1255:    *
1256:    * @since 1.4
1257:    */
1258:   public boolean isClosed()
1259:   {
1260:     SocketChannel channel = getChannel();
1261:     
1262:     return impl == null || (channel != null && ! channel.isOpen());
1263:   }
1264: 
1265:   /**
1266:    * Checks if the socket's input stream is shutdown
1267:    *
1268:    * @return True if input is shut down.
1269:    *
1270:    * @since 1.4
1271:    */
1272:   public boolean isInputShutdown()
1273:   {
1274:     return inputShutdown;
1275:   }
1276: 
1277:   /**
1278:    * Checks if the socket's output stream is shutdown
1279:    *
1280:    * @return True if output is shut down.
1281:    *
1282:    * @since 1.4
1283:    */
1284:   public boolean isOutputShutdown()
1285:   {
1286:     return outputShutdown;
1287:   }
1288: }