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 */ DatagramSocket(DatagramSocketImpl impl)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 */ DatagramSocket()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 */ DatagramSocket(int port)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 */ DatagramSocket(int port, InetAddress addr)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 */ DatagramSocket(SocketAddress address)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 getImpl()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 */ close()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 */ getInetAddress()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 */ getPort()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 */ getLocalAddress()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 */ getLocalPort()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 */ getSoTimeout()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 */ setSoTimeout(int timeout)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 */ getSendBufferSize()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 */ setSendBufferSize(int size)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 */ getReceiveBufferSize()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 */ setReceiveBufferSize(int size)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 */ connect(InetAddress address, int port)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 */ disconnect()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 */ receive(DatagramPacket p)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 */ send(DatagramPacket p)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 */ bind(SocketAddress address)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 */ isClosed()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 */ getChannel()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 */ connect(SocketAddress address)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 */ isBound()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 */ isConnected()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 */ getRemoteSocketAddress()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 */ getLocalSocketAddress()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 */ setReuseAddress(boolean on)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 */ getReuseAddress()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 */ setBroadcast(boolean enable)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 */ getBroadcast()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 */ setTrafficClass(int tc)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 */ getTrafficClass()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 */ setDatagramSocketImplFactory(DatagramSocketImplFactory fac)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 } 989