Source for java.net.DatagramSocket

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