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