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 IllegalArgumentException If address or port are invalid.
 488:    * @exception SecurityException If the caller is not allowed to send
 489:    * datagrams to or receive from this address and port.
 490:    *
 491:    * @since 1.2
 492:    */
 493:   public void connect(InetAddress address, int port)
 494:   {
 495:     if (address == null)
 496:       throw new IllegalArgumentException("Connect address may not be null");
 497: 
 498:     if ((port < 1) || (port > 65535))
 499:       throw new IllegalArgumentException("Port number is illegal: " + port);
 500: 
 501:     SecurityManager sm = System.getSecurityManager();
 502:     if (sm != null)
 503:       sm.checkConnect(address.getHostName(), port);
 504: 
 505:     try
 506:       {
 507:     getImpl().connect(address, port);
 508:     remoteAddress = address;
 509:     remotePort = port;
 510:       }
 511:     catch (SocketException e)
 512:       {
 513:     // This means simply not connected or connect not implemented.
 514:       }
 515:   }
 516: 
 517:   /**
 518:    * This method disconnects this socket from the address/port it was
 519:    * connected to.  If the socket was not connected in the first place,
 520:    * this method does nothing.
 521:    *
 522:    * @since 1.2
 523:    */
 524:   public void disconnect()
 525:   {
 526:     if (! isConnected())
 527:       return;
 528: 
 529:     try
 530:       {
 531:     getImpl().disconnect();
 532:       }
 533:     catch (SocketException e)
 534:       {
 535:     // This cannot happen as we are connected.
 536:       }
 537:     finally
 538:       {
 539:     remoteAddress = null;
 540:     remotePort = -1;
 541:       }
 542:   }
 543: 
 544:   /**
 545:    * Reads a datagram packet from the socket.  Note that this method
 546:    * will block until a packet is received from the network.  On return,
 547:    * the passed in <code>DatagramPacket</code> is populated with the data
 548:    * received and all the other information about the packet.
 549:    *
 550:    * @param p A <code>DatagramPacket</code> for storing the data
 551:    *
 552:    * @exception IOException If an error occurs.
 553:    * @exception SocketTimeoutException If setSoTimeout was previously called
 554:    * and the timeout has expired.
 555:    * @exception PortUnreachableException If the socket is connected to a
 556:    * currently unreachable destination. Note, there is no guarantee that the
 557:    * exception will be thrown.
 558:    * @exception IllegalBlockingModeException If this socket has an associated
 559:    * channel, and the channel is in non-blocking mode.
 560:    * @exception SecurityException If a security manager exists and its
 561:    * checkAccept method doesn't allow the receive.
 562:    */
 563:   public synchronized void receive(DatagramPacket p) throws IOException
 564:   {
 565:     if (isClosed())
 566:       throw new SocketException("socket is closed");
 567: 
 568:     if (remoteAddress != null && remoteAddress.isMulticastAddress())
 569:       throw new IOException
 570:     ("Socket connected to a multicast address my not receive");
 571: 
 572:     if (getChannel() != null && ! getChannel().isBlocking()
 573:         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
 574:       throw new IllegalBlockingModeException();
 575: 
 576:     getImpl().receive(p);
 577: 
 578:     SecurityManager s = System.getSecurityManager();
 579:     if (s != null && isConnected())
 580:       s.checkAccept(p.getAddress().getHostName(), p.getPort());
 581:   }
 582: 
 583:   /**
 584:    * Sends the specified packet.  The host and port to which the packet
 585:    * are to be sent should be set inside the packet.
 586:    *
 587:    * @param p The datagram packet to send.
 588:    *
 589:    * @exception IOException If an error occurs.
 590:    * @exception SecurityException If a security manager exists and its
 591:    * checkMulticast or checkConnect method doesn't allow the send.
 592:    * @exception PortUnreachableException If the socket is connected to a
 593:    * currently unreachable destination. Note, there is no guarantee that the
 594:    * exception will be thrown.
 595:    * @exception IllegalBlockingModeException If this socket has an associated
 596:    * channel, and the channel is in non-blocking mode.
 597:    */
 598:   public void send(DatagramPacket p) throws IOException
 599:   {
 600:     if (isClosed())
 601:       throw new SocketException("socket is closed");
 602: 
 603:     // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api.
 604:     SecurityManager s = System.getSecurityManager();
 605:     if (s != null && ! isConnected())
 606:       {
 607:     InetAddress addr = p.getAddress();
 608:     if (addr.isMulticastAddress())
 609:       s.checkMulticast(addr);
 610:     else
 611:       s.checkConnect(addr.getHostAddress(), p.getPort());
 612:       }
 613: 
 614:     if (isConnected())
 615:       {
 616:     if (p.getAddress() != null
 617:         && (remoteAddress != p.getAddress() || remotePort != p.getPort()))
 618:       throw new IllegalArgumentException
 619:         ("DatagramPacket address does not match remote address");
 620:       }
 621: 
 622:     // FIXME: if this is a subclass of MulticastSocket,
 623:     // use getTimeToLive for TTL val.
 624:     if (getChannel() != null && ! getChannel().isBlocking()
 625:         && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
 626:       throw new IllegalBlockingModeException();
 627: 
 628:     getImpl().send(p);
 629:   }
 630: 
 631:   /**
 632:    * Binds the socket to the given socket address.
 633:    *
 634:    * @param address The socket address to bind to.
 635:    *
 636:    * @exception SocketException If an error occurs.
 637:    * @exception SecurityException If a security manager exists and
 638:    * its checkListen method doesn't allow the operation.
 639:    * @exception IllegalArgumentException If address type is not supported.
 640:    *
 641:    * @since 1.4
 642:    */
 643:   public void bind(SocketAddress address) throws SocketException
 644:   {
 645:     if (isClosed())
 646:       throw new SocketException("socket is closed");
 647: 
 648:     if (! (address instanceof InetSocketAddress))
 649:       throw new IllegalArgumentException("unsupported address type");
 650: 
 651:     InetAddress addr = ((InetSocketAddress) address).getAddress();
 652:     int port = ((InetSocketAddress) address).getPort();
 653: 
 654:     if (port < 0 || port > 65535)
 655:       throw new IllegalArgumentException("Invalid port: " + port);
 656: 
 657:     SecurityManager s = System.getSecurityManager();
 658:     if (s != null)
 659:       s.checkListen(port);
 660: 
 661:     if (addr == null)
 662:       addr = InetAddress.ANY_IF;
 663: 
 664:     try
 665:       {
 666:     getImpl().bind(port, addr);
 667:     bound = true;
 668:       }
 669:     catch (SocketException exception)
 670:       {
 671:     getImpl().close();
 672:     throw exception;
 673:       }
 674:     catch (RuntimeException exception)
 675:       {
 676:     getImpl().close();
 677:     throw exception;
 678:       }
 679:     catch (Error error)
 680:       {
 681:     getImpl().close();
 682:     throw error;
 683:       }
 684:   }
 685: 
 686:   /**
 687:    * Checks if the datagram socket is closed.
 688:    *
 689:    * @return True if socket is closed, false otherwise.
 690:    *
 691:    * @since 1.4
 692:    */
 693:   public boolean isClosed()
 694:   {
 695:     return impl == null;
 696:   }
 697: 
 698:   /**
 699:    * Returns the datagram channel assoziated with this datagram socket.
 700:    *
 701:    * @return The associated <code>DatagramChannel</code> object or null
 702:    *
 703:    * @since 1.4
 704:    */
 705:   public DatagramChannel getChannel()
 706:   {
 707:     return null;
 708:   }
 709: 
 710:   /**
 711:    * Connects the datagram socket to a specified socket address.
 712:    *
 713:    * @param address The socket address to connect to.
 714:    *
 715:    * @exception SocketException If an error occurs.
 716:    * @exception IllegalArgumentException If address type is not supported.
 717:    *
 718:    * @since 1.4
 719:    */
 720:   public void connect(SocketAddress address) throws SocketException
 721:   {
 722:     if (isClosed())
 723:       throw new SocketException("socket is closed");
 724: 
 725:     if (! (address instanceof InetSocketAddress))
 726:       throw new IllegalArgumentException("unsupported address type");
 727: 
 728:     InetSocketAddress tmp = (InetSocketAddress) address;
 729:     connect(tmp.getAddress(), tmp.getPort());
 730:   }
 731: 
 732:   /**
 733:    * Returns the binding state of the socket.
 734:    *
 735:    * @return True if socket bound, false otherwise.
 736:    *
 737:    * @since 1.4
 738:    */
 739:   public boolean isBound()
 740:   {
 741:     return bound;
 742:   }
 743: 
 744:   /**
 745:    * Returns the connection state of the socket.
 746:    *
 747:    * @return True if socket is connected, false otherwise.
 748:    *
 749:    * @since 1.4
 750:    */
 751:   public boolean isConnected()
 752:   {
 753:     return remoteAddress != null;
 754:   }
 755: 
 756:   /**
 757:    * Returns the SocketAddress of the host this socket is conneted to
 758:    * or null if this socket is not connected.
 759:    *
 760:    * @return The socket address of the remote host if connected or null
 761:    *
 762:    * @since 1.4
 763:    */
 764:   public SocketAddress getRemoteSocketAddress()
 765:   {
 766:     if (! isConnected())
 767:       return null;
 768: 
 769:     return new InetSocketAddress(remoteAddress, remotePort);
 770:   }
 771: 
 772:   /**
 773:    * Returns the local SocketAddress this socket is bound to.
 774:    *
 775:    * @return The local SocketAddress or null if the socket is not bound.
 776:    *
 777:    * @since 1.4
 778:    */
 779:   public SocketAddress getLocalSocketAddress()
 780:   {
 781:     if (! isBound())
 782:       return null;
 783: 
 784:     return new InetSocketAddress(getLocalAddress(), getLocalPort());
 785:   }
 786: 
 787:   /**
 788:    * Enables/Disables SO_REUSEADDR.
 789:    *
 790:    * @param on Whether or not to have SO_REUSEADDR turned on.
 791:    *
 792:    * @exception SocketException If an error occurs.
 793:    *
 794:    * @since 1.4
 795:    */
 796:   public void setReuseAddress(boolean on) throws SocketException
 797:   {
 798:     if (isClosed())
 799:       throw new SocketException("socket is closed");
 800: 
 801:     getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
 802:   }
 803: 
 804:   /**
 805:    * Checks if SO_REUSEADDR is enabled.
 806:    *
 807:    * @return True if SO_REUSEADDR is set on the socket, false otherwise.
 808:    *
 809:    * @exception SocketException If an error occurs.
 810:    *
 811:    * @since 1.4
 812:    */
 813:   public boolean getReuseAddress() throws SocketException
 814:   {
 815:     if (isClosed())
 816:       throw new SocketException("socket is closed");
 817: 
 818:     Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR);
 819: 
 820:     if (buf instanceof Boolean)
 821:       return ((Boolean) buf).booleanValue();
 822: 
 823:     throw new SocketException("unexpected type");
 824:   }
 825: 
 826:   /**
 827:    * Enables/Disables SO_BROADCAST
 828:    *
 829:    * @param enable True if SO_BROADCAST should be enabled, false otherwise.
 830:    *
 831:    * @exception SocketException If an error occurs
 832:    *
 833:    * @since 1.4
 834:    */
 835:   public void setBroadcast(boolean enable) throws SocketException
 836:   {
 837:     if (isClosed())
 838:       throw new SocketException("socket is closed");
 839: 
 840:     getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable));
 841:   }
 842: 
 843:   /**
 844:    * Checks if SO_BROADCAST is enabled
 845:    *
 846:    * @return Whether SO_BROADCAST is set
 847:    *
 848:    * @exception SocketException If an error occurs
 849:    *
 850:    * @since 1.4
 851:    */
 852:   public boolean getBroadcast() throws SocketException
 853:   {
 854:     if (isClosed())
 855:       throw new SocketException("socket is closed");
 856: 
 857:     Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST);
 858: 
 859:     if (buf instanceof Boolean)
 860:       return ((Boolean) buf).booleanValue();
 861: 
 862:     throw new SocketException("unexpected type");
 863:   }
 864: 
 865:   /**
 866:    * Sets the traffic class value
 867:    *
 868:    * @param tc The traffic class
 869:    *
 870:    * @exception SocketException If an error occurs
 871:    * @exception IllegalArgumentException If tc value is illegal
 872:    *
 873:    * @see DatagramSocket#getTrafficClass()
 874:    *
 875:    * @since 1.4
 876:    */
 877:   public void setTrafficClass(int tc) throws SocketException
 878:   {
 879:     if (isClosed())
 880:       throw new SocketException("socket is closed");
 881: 
 882:     if (tc < 0 || tc > 255)
 883:       throw new IllegalArgumentException();
 884: 
 885:     getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc));
 886:   }
 887: 
 888:   /**
 889:    * Returns the current traffic class
 890:    *
 891:    * @return The current traffic class.
 892:    *
 893:    * @see DatagramSocket#setTrafficClass(int tc)
 894:    *
 895:    * @exception SocketException If an error occurs
 896:    *
 897:    * @since 1.4
 898:    */
 899:   public int getTrafficClass() throws SocketException
 900:   {
 901:     if (isClosed())
 902:       throw new SocketException("socket is closed");
 903: 
 904:     Object buf = getImpl().getOption(SocketOptions.IP_TOS);
 905: 
 906:     if (buf instanceof Integer)
 907:       return ((Integer) buf).intValue();
 908: 
 909:     throw new SocketException("unexpected type");
 910:   }
 911: 
 912:   /**
 913:    * Sets the datagram socket implementation factory for the application
 914:    *
 915:    * @param fac The factory to set
 916:    *
 917:    * @exception IOException If an error occurs
 918:    * @exception SocketException If the factory is already defined
 919:    * @exception SecurityException If a security manager exists and its
 920:    * checkSetFactory method doesn't allow the operation
 921:    */
 922:   public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac)
 923:     throws IOException
 924:   {
 925:     if (factory != null)
 926:       throw new SocketException("DatagramSocketImplFactory already defined");
 927: 
 928:     SecurityManager sm = System.getSecurityManager();
 929:     if (sm != null)
 930:       sm.checkSetFactory();
 931: 
 932:     factory = fac;
 933:   }
 934: }