Source for java.net.DatagramSocket

   1: /* DatagramSocket.java -- A class to model UDP sockets
   2:    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
   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.classpath.SystemProperties;
  42: 
  43: import gnu.java.net.PlainDatagramSocketImpl;
  44: import gnu.java.nio.DatagramChannelImpl;
  45: 
  46: import java.io.IOException;
  47: import java.nio.channels.DatagramChannel;
  48: import java.nio.channels.IllegalBlockingModeException;
  49: 
  50: 
  51: /**
  52:  * Written using on-line Java Platform 1.2 API Specification, as well
  53:  * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
  54:  * Status:  Believed complete and correct.
  55:  */
  56: /**
  57:  * This class models a connectionless datagram socket that sends
  58:  * individual packets of data across the network.  In the TCP/IP world,
  59:  * this means UDP.  Datagram packets do not have guaranteed delivery,
  60:  * or any guarantee about the order the data will be received on the
  61:  * remote host.
  62:  *
  63:  * @author Aaron M. Renn (arenn@urbanophile.com)
  64:  * @author Warren Levy (warrenl@cygnus.com)
  65:  * @date May 3, 1999.
  66:  */
  67: public class DatagramSocket
  68: {
  69:   /**
  70:    * This is the user DatagramSocketImplFactory for this class.  If this
  71:    * variable is null, a default factory is used.
  72:    */
  73:   private static DatagramSocketImplFactory factory;
  74: 
  75:   /**
  76:    * This is the implementation object used by this socket.
  77:    */
  78:   private DatagramSocketImpl impl;
  79: 
  80:   /**
  81:    * True if socket implementation was created.
  82:    */
  83:   private boolean implCreated;
  84: 
  85:   /**
  86:    * This is the address we are "connected" to
  87:    */
  88:   private InetAddress remoteAddress;
  89: 
  90:   /**
  91:    * This is the port we are "connected" to
  92:    */
  93:   private int remotePort = -1;
  94: 
  95:   /**
  96:    * True if socket is bound.
  97:    */
  98:   private boolean bound;
  99: 
 100:   /**
 101:    * Creates a <code>DatagramSocket</code> from a specified
 102:    * <code>DatagramSocketImpl</code> instance
 103:    *
 104:    * @param impl The <code>DatagramSocketImpl</code> the socket will be
 105:    * created from
 106:    *
 107:    * @since 1.4
 108:    */
 109:   protected DatagramSocket(DatagramSocketImpl impl)
 110:   {
 111:     if (impl == null)
 112:       throw new NullPointerException("impl may not be null");
 113: 
 114:     this.impl = impl;
 115:     this.remoteAddress = null;
 116:     this.remotePort = -1;
 117:   }
 118: 
 119:   /**
 120:    * Initializes a new instance of <code>DatagramSocket</code> that binds to
 121:    * a random port and every address on the local machine.
 122:    *
 123:    * @exception SocketException If an error occurs.
 124:    * @exception SecurityException If a security manager exists and
 125:    * its <code>checkListen</code> method doesn't allow the operation.
 126:    */
 127:   public DatagramSocket() throws SocketException
 128:   {
 129:     this(new InetSocketAddress(0));
 130:   }
 131: 
 132:   /**
 133:    * Initializes a new instance of <code>DatagramSocket</code> that binds to
 134:    * the specified port and every address on the local machine.
 135:    *
 136:    * @param port The local port number to bind to.
 137:    *
 138:    * @exception SecurityException If a security manager exists and its
 139:    * <code>checkListen</code> method doesn't allow the operation.
 140:    * @exception SocketException If an error occurs.
 141:    */
 142:   public DatagramSocket(int port) throws SocketException
 143:   {
 144:     this(new InetSocketAddress(port));
 145:   }
 146: 
 147:   /**
 148:    * Initializes a new instance of <code>DatagramSocket</code> that binds to
 149:    * the specified local port and address.
 150:    *
 151:    * @param port The local port number to bind to.
 152:    * @param addr The local address to bind to.
 153:    *
 154:    * @exception SecurityException If a security manager exists and its
 155:    * checkListen method doesn't allow the operation.
 156:    * @exception SocketException If an error occurs.
 157:    */
 158:   public DatagramSocket(int port, InetAddress addr) throws SocketException
 159:   {
 160:     this(new InetSocketAddress(addr, port));
 161:   }
 162: 
 163:   /**
 164:    * Initializes a new instance of <code>DatagramSocket</code> that binds to
 165:    * the specified local port and address.
 166:    *
 167:    * @param address The local address and port number to bind to.
 168:    *
 169:    * @exception SecurityException If a security manager exists and its
 170:    * <code>checkListen</code> method doesn't allow the operation.
 171:    * @exception SocketException If an error occurs.
 172:    *
 173:    * @since 1.4
 174:    */
 175:   public DatagramSocket(SocketAddress address) throws SocketException
 176:   {
 177:     String propVal = SystemProperties.getProperty("impl.prefix");
 178:     if (propVal == null || propVal.equals(""))
 179:       {
 180:         if (factory != null)
 181:           impl = factory.createDatagramSocketImpl();
 182:         else
 183:           {
 184:             try
 185:               {
 186:                 impl = new PlainDatagramSocketImpl();
 187:               }
 188:             catch (IOException ioe)
 189:               {
 190:                 SocketException se = new SocketException();
 191:                 se.initCause(ioe);
 192:                 throw se;
 193:               }
 194:           }
 195:       }
 196:     else
 197:       try
 198:         {
 199:       impl =
 200:         (DatagramSocketImpl) Class.forName("java.net." + propVal
 201:                                            + "DatagramSocketImpl")
 202:                                   .newInstance();
 203:         }
 204:       catch (Exception e)
 205:         {
 206:       System.err.println("Could not instantiate class: java.net."
 207:                          + propVal + "DatagramSocketImpl");
 208:           try
 209:             {
 210:               impl = new PlainDatagramSocketImpl();
 211:             }
 212:           catch (IOException ioe)
 213:             {
 214:               SocketException se = new SocketException();
 215:               se.initCause(ioe);
 216:               throw se;
 217:             }
 218:         }
 219: 
 220:     if (address != null)
 221:       bind(address);
 222:   }
 223: 
 224:   // This needs to be accessible from java.net.MulticastSocket
 225:   DatagramSocketImpl getImpl() throws SocketException
 226:   {
 227:     try
 228:       {
 229:     if (! implCreated)
 230:       {
 231:         impl.create();
 232:         implCreated = true;
 233:       }
 234: 
 235:     return impl;
 236:       }
 237:     catch (IOException e)
 238:       {
 239:     SocketException se = new SocketException();
 240:     se.initCause(e);
 241:     throw se;
 242:       }
 243:   }
 244: 
 245:   /**
 246:    * Closes this datagram socket.
 247:    */
 248:   public void close()
 249:   {
 250:     if (isClosed())
 251:       return;
 252: 
 253:     try
 254:       {
 255:     getImpl().close();
 256:       }
 257:     catch (SocketException e)
 258:       {
 259:     // Ignore this case, just close the socket in finally clause.
 260:       }
 261:     finally
 262:       {
 263:     remoteAddress = null;
 264:     remotePort = -1;
 265:     impl = null;
 266:       }
 267: 
 268:     try
 269:       {
 270:     if (getChannel() != null)
 271:       getChannel().close();
 272:       }
 273:     catch (IOException e)
 274:       {
 275:     // Do nothing.
 276:       }
 277:   }
 278: 
 279:   /**
 280:    * This method returns the remote address to which this socket is
 281:    * connected.  If this socket is not connected, then this method will
 282:    * return <code>null</code>.
 283:    *
 284:    * @return The remote address.
 285:    *
 286:    * @since 1.2
 287:    */
 288:   public InetAddress getInetAddress()
 289:   {
 290:     return remoteAddress;
 291:   }
 292: 
 293:   /**
 294:    * This method returns the remote port to which this socket is
 295:    * connected.  If this socket is not connected, then this method will
 296:    * return -1.
 297:    *
 298:    * @return The remote port.
 299:    *
 300:    * @since 1.2
 301:    */
 302:   public int getPort()
 303:   {
 304:     return remotePort;
 305:   }
 306: 
 307:   /**
 308:    * Returns the local address this datagram socket is bound to.
 309:    *
 310:    * @return The local address is the socket is bound or null
 311:    *
 312:    * @since 1.1
 313:    */
 314:   public InetAddress getLocalAddress()
 315:   {
 316:     if (! isBound())
 317:       return null;
 318: 
 319:     InetAddress localAddr;
 320: 
 321:     try
 322:       {
 323:     localAddr =
 324:       (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
 325: 
 326:     SecurityManager s = System.getSecurityManager();
 327:     if (s != null)
 328:       s.checkConnect(localAddr.getHostAddress(), -1);
 329:       }
 330:     catch (SecurityException e)
 331:       {
 332:     localAddr = InetAddress.ANY_IF;
 333:       }
 334:     catch (SocketException e)
 335:       {
 336:     // This cannot happen as we are bound.
 337:     return null;
 338:       }
 339: 
 340:     return localAddr;
 341:   }
 342: 
 343:   /**
 344:    * Returns the local port this socket is bound to.
 345:    *
 346:    * @return The local port number.
 347:    */
 348:   public int getLocalPort()
 349:   {
 350:     if (isClosed())
 351:       return -1;
 352: 
 353:     try
 354:       {
 355:     return getImpl().getLocalPort();
 356:       }
 357:     catch (SocketException e)
 358:       {
 359:     // This cannot happen as we are bound.
 360:     return 0;
 361:       }
 362:   }
 363: 
 364:   /**
 365:    * Returns the value of the socket's SO_TIMEOUT setting.  If this method
 366:    * returns 0 then SO_TIMEOUT is disabled.
 367:    *
 368:    * @return The current timeout in milliseconds.
 369:    *
 370:    * @exception SocketException If an error occurs.
 371:    *
 372:    * @since 1.1
 373:    */
 374:   public synchronized int getSoTimeout() throws SocketException
 375:   {
 376:     if (isClosed())
 377:       throw new SocketException("socket is closed");
 378: 
 379:     Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT);
 380: 
 381:     if (buf instanceof Integer)
 382:       return ((Integer) buf).intValue();
 383: 
 384:     throw new SocketException("unexpected type");
 385:   }
 386: 
 387:   /**
 388:    * Sets the value of the socket's SO_TIMEOUT value.  A value of 0 will
 389:    * disable SO_TIMEOUT.  Any other value is the number of milliseconds
 390:    * a socket read/write will block before timing out.
 391:    *
 392:    * @param timeout The new SO_TIMEOUT value in milliseconds.
 393:    *
 394:    * @exception SocketException If an error occurs.
 395:    *
 396:    * @since 1.1
 397:    */
 398:   public synchronized void setSoTimeout(int timeout) throws SocketException
 399:   {
 400:     if (isClosed())
 401:       throw new SocketException("socket is closed");
 402: 
 403:     if (timeout < 0)
 404:       throw new IllegalArgumentException("Invalid timeout: " + timeout);
 405: 
 406:     getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
 407:   }
 408: 
 409:   /**
 410:    * This method returns the value of the system level socket option
 411:    * SO_SNDBUF, which is used by the operating system to tune buffer
 412:    * sizes for data transfers.
 413:    *
 414:    * @return The send buffer size.
 415:    *
 416:    * @exception SocketException If an error occurs.
 417:    *
 418:    * @since 1.2
 419:    */
 420:   public int getSendBufferSize() throws SocketException
 421:   {
 422:     if (isClosed())
 423:       throw new SocketException("socket is closed");
 424: 
 425:     Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
 426: 
 427:     if (buf instanceof Integer)
 428:       return ((Integer) buf).intValue();
 429: 
 430:     throw new SocketException("unexpected type");
 431:   }
 432: 
 433:   /**
 434:    * This method sets the value for the system level socket option
 435:    * SO_SNDBUF to the specified value.  Note that valid values for this
 436:    * option are specific to a given operating system.
 437:    *
 438:    * @param size The new send buffer size.
 439:    *
 440:    * @exception SocketException If an error occurs.
 441:    * @exception IllegalArgumentException If size is 0 or negative.
 442:    *
 443:    * @since 1.2
 444:    */
 445:   public void setSendBufferSize(int size) throws SocketException
 446:   {
 447:     if (isClosed())
 448:       throw new SocketException("socket is closed");
 449: 
 450:     if (size < 0)
 451:       throw new IllegalArgumentException("Buffer size is less than 0");
 452: 
 453:     getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
 454:   }
 455: 
 456:   /**
 457:    * This method returns the value of the system level socket option
 458:    * SO_RCVBUF, which is used by the operating system to tune buffer
 459:    * sizes for data transfers.
 460:    *
 461:    * @return The receive buffer size.
 462:    *
 463:    * @exception SocketException If an error occurs.
 464:    *
 465:    * @since 1.2
 466:    */
 467:   public int getReceiveBufferSize() throws SocketException
 468:   {
 469:     if (isClosed())
 470:       throw new SocketException("socket is closed");
 471: 
 472:     Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
 473: 
 474:     if (buf instanceof Integer)
 475:       return ((Integer) buf).intValue();
 476: 
 477:     throw new SocketException("unexpected type");
 478:   }
 479: 
 480:   /**
 481:    * This method sets the value for the system level socket option
 482:    * SO_RCVBUF to the specified value.  Note that valid values for this
 483:    * option are specific to a given operating system.
 484:    *
 485:    * @param size The new receive buffer size.
 486:    *
 487:    * @exception SocketException If an error occurs.
 488:    * @exception IllegalArgumentException If size is 0 or negative.
 489:    *
 490:    * @since 1.2
 491:    */
 492:   public void setReceiveBufferSize(int size) throws SocketException
 493:   {
 494:     if (isClosed())
 495:       throw new SocketException("socket is closed");
 496: 
 497:     if (size < 0)
 498:       throw new IllegalArgumentException("Buffer size is less than 0");
 499: 
 500:     getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
 501:   }
 502: 
 503:   /**
 504:    * This method connects this socket to the specified address and port.
 505:    * When a datagram socket is connected, it will only send or receive
 506:    * packets to and from the host to which it is connected. A multicast
 507:    * socket that is connected may only send and not receive packets.
 508:    *
 509:    * @param address The address to connect this socket to.
 510:    * @param port The port to connect this socket to.
 511:    *
 512:    * @exception IllegalArgumentException If address or port are invalid.
 513:    * @exception SecurityException If the caller is not allowed to send
 514:    * datagrams to or receive from this address and port.
 515:    *
 516:    * @since 1.2
 517:    */
 518:   public void connect(InetAddress address, int port)
 519:   {
 520:     if (address == null)
 521:       throw new IllegalArgumentException("Connect address may not be null");
 522: 
 523:     if ((port < 1) || (port > 65535))
 524:       throw new IllegalArgumentException("Port number is illegal: " + port);
 525: 
 526:     SecurityManager sm = System.getSecurityManager();
 527:     if (sm != null)
 528:       sm.checkConnect(address.getHostAddress(), port);
 529: 
 530:     try
 531:       {
 532:     getImpl().connect(address, port);
 533:     remoteAddress = address;
 534:     remotePort = port;
 535:       }
 536:     catch (SocketException e)
 537:       {
 538:     // This means simply not connected or connect not implemented.
 539:       }
 540:   }
 541: 
 542:   /**
 543:    * This method disconnects this socket from the address/port it was
 544:    * connected to.  If the socket was not connected in the first place,
 545:    * this method does nothing.
 546:    *
 547:    * @since 1.2
 548:    */
 549:   public void disconnect()
 550:   {
 551:     if (! isConnected())
 552:       return;
 553: 
 554:     try
 555:       {
 556:     getImpl().disconnect();
 557:       }
 558:     catch (SocketException e)
 559:       {
 560:     // This cannot happen as we are connected.
 561:       }
 562:     finally
 563:       {
 564:     remoteAddress = null;
 565:     remotePort = -1;
 566:       }
 567:   }
 568: 
 569:   /**
 570:    * Reads a datagram packet from the socket.  Note that this method
 571:    * will block until a packet is received from the network.  On return,
 572:    * the passed in <code>DatagramPacket</code> is populated with the data
 573:    * received and all the other information about the packet.
 574:    *
 575:    * @param p A <code>DatagramPacket</code> for storing the data
 576:    *
 577:    * @exception IOException If an error occurs.
 578:    * @exception SocketTimeoutException If setSoTimeout was previously called
 579:    * and the timeout has expired.
 580:    * @exception PortUnreachableException If the socket is connected to a
 581:    * currently unreachable destination. Note, there is no guarantee that the
 582:    * exception will be thrown.
 583:    * @exception IllegalBlockingModeException If this socket has an associated
 584:    * channel, and the channel is in non-blocking mode.
 585:    * @exception SecurityException If a security manager exists and its
 586:    * checkAccept method doesn't allow the receive.
 587:    */
 588:   public synchronized void receive(DatagramPacket p) throws IOException
 589:   {
 590:     if (isClosed())
 591:       throw new SocketException("socket is closed");
 592: 
 593:     if (remoteAddress != null && remoteAddress.isMulticastAddress())
 594:       throw new IOException
 595:     ("Socket connected to a multicast address my not receive");
 596: 
 597:     if (getChannel() != null && ! getChannel().isBlocking()
 598:         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
 599:       throw new IllegalBlockingModeException();
 600: 
 601:     DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen);
 602:     getImpl().receive(p2);
 603:     p.length = p2.length;
 604:     if (p2.getAddress() != null)
 605:       p.setAddress(p2.getAddress());
 606:     if (p2.getPort() != -1)
 607:       p.setPort(p2.getPort());
 608: 
 609:     SecurityManager s = System.getSecurityManager();
 610:     if (s != null && isConnected())
 611:       s.checkAccept(p.getAddress().getHostAddress(), p.getPort());
 612:   }
 613: 
 614:   /**
 615:    * Sends the specified packet.  The host and port to which the packet
 616:    * are to be sent should be set inside the packet.
 617:    *
 618:    * @param p The datagram packet to send.
 619:    *
 620:    * @exception IOException If an error occurs.
 621:    * @exception SecurityException If a security manager exists and its
 622:    * checkMulticast or checkConnect method doesn't allow the send.
 623:    * @exception PortUnreachableException If the socket is connected to a
 624:    * currently unreachable destination. Note, there is no guarantee that the
 625:    * exception will be thrown.
 626:    * @exception IllegalBlockingModeException If this socket has an associated
 627:    * channel, and the channel is in non-blocking mode.
 628:    */
 629:   public void send(DatagramPacket p) throws IOException
 630:   {
 631:     if (isClosed())
 632:       throw new SocketException("socket is closed");
 633: 
 634:     // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
 635:     SecurityManager s = System.getSecurityManager();
 636:     if (s != null && ! isConnected())
 637:       {
 638:     InetAddress addr = p.getAddress();
 639:     if (addr.isMulticastAddress())
 640:       s.checkMulticast(addr);
 641:     else
 642:       s.checkConnect(addr.getHostAddress(), p.getPort());
 643:       }
 644: 
 645:     if (isConnected())
 646:       {
 647:     if (p.getAddress() != null
 648:         && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
 649:       throw new IllegalArgumentException
 650:         ("DatagramPacket address does not match remote address");
 651:       }
 652: 
 653:     // FIXME: if this is a subclass of MulticastSocket,
 654:     // use getTimeToLive for TTL val.
 655:     if (getChannel() != null && ! getChannel().isBlocking()
 656:         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
 657:       throw new IllegalBlockingModeException();
 658: 
 659:     getImpl().send(p);
 660:   }
 661: 
 662:   /**
 663:    * Binds the socket to the given socket address.
 664:    *
 665:    * @param address The socket address to bind to.
 666:    *
 667:    * @exception SocketException If an error occurs.
 668:    * @exception SecurityException If a security manager exists and
 669:    * its checkListen method doesn't allow the operation.
 670:    * @exception IllegalArgumentException If address type is not supported.
 671:    *
 672:    * @since 1.4
 673:    */
 674:   public void bind(SocketAddress address) throws SocketException
 675:   {
 676:     if (isClosed())
 677:       throw new SocketException("socket is closed");
 678:     
 679:     if (address == null)
 680:       address = new InetSocketAddress(InetAddress.ANY_IF, 0);
 681: 
 682:     if (! (address instanceof InetSocketAddress))
 683:       throw new IllegalArgumentException("unsupported address type");
 684: 
 685:     InetAddress addr = ((InetSocketAddress) address).getAddress();
 686:     int port = ((InetSocketAddress) address).getPort();
 687: 
 688:     if (port < 0 || port > 65535)
 689:       throw new IllegalArgumentException("Invalid port: " + port);
 690: 
 691:     SecurityManager s = System.getSecurityManager();
 692:     if (s != null)
 693:       s.checkListen(port);
 694: 
 695:     if (addr == null)
 696:       addr = InetAddress.ANY_IF;
 697: 
 698:     try
 699:       {
 700:     getImpl().bind(port, addr);
 701:     bound = true;
 702:       }
 703:     catch (SocketException exception)
 704:       {
 705:     getImpl().close();
 706:     throw exception;
 707:       }
 708:     catch (RuntimeException exception)
 709:       {
 710:     getImpl().close();
 711:     throw exception;
 712:       }
 713:     catch (Error error)
 714:       {
 715:     getImpl().close();
 716:     throw error;
 717:       }
 718:   }
 719: 
 720:   /**
 721:    * Checks if the datagram socket is closed.
 722:    *
 723:    * @return True if socket is closed, false otherwise.
 724:    *
 725:    * @since 1.4
 726:    */
 727:   public boolean isClosed()
 728:   {
 729:     return impl == null;
 730:   }
 731: 
 732:   /**
 733:    * Returns the datagram channel assoziated with this datagram socket.
 734:    *
 735:    * @return The associated <code>DatagramChannel</code> object or null
 736:    *
 737:    * @since 1.4
 738:    */
 739:   public DatagramChannel getChannel()
 740:   {
 741:     return null;
 742:   }
 743: 
 744:   /**
 745:    * Connects the datagram socket to a specified socket address.
 746:    *
 747:    * @param address The socket address to connect to.
 748:    *
 749:    * @exception SocketException If an error occurs.
 750:    * @exception IllegalArgumentException If address type is not supported.
 751:    *
 752:    * @since 1.4
 753:    */
 754:   public void connect(SocketAddress address) throws SocketException
 755:   {
 756:     if (isClosed())
 757:       throw new SocketException("socket is closed");
 758: 
 759:     if (! (address instanceof InetSocketAddress))
 760:       throw new IllegalArgumentException("unsupported address type");
 761: 
 762:     InetSocketAddress tmp = (InetSocketAddress) address;
 763:     connect(tmp.getAddress(), tmp.getPort());
 764:   }
 765: 
 766:   /**
 767:    * Returns the binding state of the socket.
 768:    *
 769:    * @return True if socket bound, false otherwise.
 770:    *
 771:    * @since 1.4
 772:    */
 773:   public boolean isBound()
 774:   {
 775:     return bound;
 776:   }
 777: 
 778:   /**
 779:    * Returns the connection state of the socket.
 780:    *
 781:    * @return True if socket is connected, false otherwise.
 782:    *
 783:    * @since 1.4
 784:    */
 785:   public boolean isConnected()
 786:   {
 787:     return remoteAddress != null;
 788:   }
 789: 
 790:   /**
 791:    * Returns the SocketAddress of the host this socket is conneted to
 792:    * or null if this socket is not connected.
 793:    *
 794:    * @return The socket address of the remote host if connected or null
 795:    *
 796:    * @since 1.4
 797:    */
 798:   public SocketAddress getRemoteSocketAddress()
 799:   {
 800:     if (! isConnected())
 801:       return null;
 802: 
 803:     return new InetSocketAddress(remoteAddress, remotePort);
 804:   }
 805: 
 806:   /**
 807:    * Returns the local SocketAddress this socket is bound to.
 808:    *
 809:    * @return The local SocketAddress or null if the socket is not bound.
 810:    *
 811:    * @since 1.4
 812:    */
 813:   public SocketAddress getLocalSocketAddress()
 814:   {
 815:     if (! isBound())
 816:       return null;
 817: 
 818:     return new InetSocketAddress(getLocalAddress(), getLocalPort());
 819:   }
 820: 
 821:   /**
 822:    * Enables/Disables SO_REUSEADDR.
 823:    *
 824:    * @param on Whether or not to have SO_REUSEADDR turned on.
 825:    *
 826:    * @exception SocketException If an error occurs.
 827:    *
 828:    * @since 1.4
 829:    */
 830:   public void setReuseAddress(boolean on) throws SocketException
 831:   {
 832:     if (isClosed())
 833:       throw new SocketException("socket is closed");
 834: 
 835:     getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
 836:   }
 837: 
 838:   /**
 839:    * Checks if SO_REUSEADDR is enabled.
 840:    *
 841:    * @return True if SO_REUSEADDR is set on the socket, false otherwise.
 842:    *
 843:    * @exception SocketException If an error occurs.
 844:    *
 845:    * @since 1.4
 846:    */
 847:   public boolean getReuseAddress() throws SocketException
 848:   {
 849:     if (isClosed())
 850:       throw new SocketException("socket is closed");
 851: 
 852:     Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
 853: 
 854:     if (buf instanceof Boolean)
 855:       return ((Boolean) buf).booleanValue();
 856: 
 857:     throw new SocketException("unexpected type");
 858:   }
 859: 
 860:   /**
 861:    * Enables/Disables SO_BROADCAST
 862:    *
 863:    * @param enable True if SO_BROADCAST should be enabled, false otherwise.
 864:    *
 865:    * @exception SocketException If an error occurs
 866:    *
 867:    * @since 1.4
 868:    */
 869:   public void setBroadcast(boolean enable) throws SocketException
 870:   {
 871:     if (isClosed())
 872:       throw new SocketException("socket is closed");
 873: 
 874:     getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
 875:   }
 876: 
 877:   /**
 878:    * Checks if SO_BROADCAST is enabled
 879:    *
 880:    * @return Whether SO_BROADCAST is set
 881:    *
 882:    * @exception SocketException If an error occurs
 883:    *
 884:    * @since 1.4
 885:    */
 886:   public boolean getBroadcast() throws SocketException
 887:   {
 888:     if (isClosed())
 889:       throw new SocketException("socket is closed");
 890: 
 891:     Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
 892: 
 893:     if (buf instanceof Boolean)
 894:       return ((Boolean) buf).booleanValue();
 895: 
 896:     throw new SocketException("unexpected type");
 897:   }
 898: 
 899:   /**
 900:    * Sets the traffic class value
 901:    *
 902:    * @param tc The traffic class
 903:    *
 904:    * @exception SocketException If an error occurs
 905:    * @exception IllegalArgumentException If tc value is illegal
 906:    *
 907:    * @see DatagramSocket#getTrafficClass()
 908:    *
 909:    * @since 1.4
 910:    */
 911:   public void setTrafficClass(int tc) throws SocketException
 912:   {
 913:     if (isClosed())
 914:       throw new SocketException("socket is closed");
 915: 
 916:     if (tc < 0 || tc > 255)
 917:       throw new IllegalArgumentException();
 918: 
 919:     getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
 920:   }
 921: 
 922:   /**
 923:    * Returns the current traffic class
 924:    *
 925:    * @return The current traffic class.
 926:    *
 927:    * @see DatagramSocket#setTrafficClass(int tc)
 928:    *
 929:    * @exception SocketException If an error occurs
 930:    *
 931:    * @since 1.4
 932:    */
 933:   public int getTrafficClass() throws SocketException
 934:   {
 935:     if (isClosed())
 936:       throw new SocketException("socket is closed");
 937: 
 938:     Object buf = getImpl().getOption(SocketOptions.IP_TOS);
 939: 
 940:     if (buf instanceof Integer)
 941:       return ((Integer) buf).intValue();
 942: 
 943:     throw new SocketException("unexpected type");
 944:   }
 945: 
 946:   /**
 947:    * Sets the datagram socket implementation factory for the application
 948:    *
 949:    * @param fac The factory to set
 950:    *
 951:    * @exception IOException If an error occurs
 952:    * @exception SocketException If the factory is already defined
 953:    * @exception SecurityException If a security manager exists and its
 954:    * checkSetFactory method doesn't allow the operation
 955:    */
 956:   public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
 957:     throws IOException
 958:   {
 959:     if (factory != null)
 960:       throw new SocketException("DatagramSocketImplFactory already defined");
 961: 
 962:     SecurityManager sm = System.getSecurityManager();
 963:     if (sm != null)
 964:       sm.checkSetFactory();
 965: 
 966:     factory = fac;
 967:   }
 968: }