Source for java.net.Socket

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