Source for java.net.DatagramSocket

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