Source for java.net.DatagramSocket

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