001/* DatagramSocket.java -- A class to model UDP sockets 002 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 003 Free Software Foundation, Inc. 004 005This file is part of GNU Classpath. 006 007GNU Classpath is free software; you can redistribute it and/or modify 008it under the terms of the GNU General Public License as published by 009the Free Software Foundation; either version 2, or (at your option) 010any later version. 011 012GNU Classpath is distributed in the hope that it will be useful, but 013WITHOUT ANY WARRANTY; without even the implied warranty of 014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015General Public License for more details. 016 017You should have received a copy of the GNU General Public License 018along with GNU Classpath; see the file COPYING. If not, write to the 019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02002110-1301 USA. 021 022Linking this library statically or dynamically with other modules is 023making a combined work based on this library. Thus, the terms and 024conditions of the GNU General Public License cover the whole 025combination. 026 027As a special exception, the copyright holders of this library give you 028permission to link this library with independent modules to produce an 029executable, regardless of the license terms of these independent 030modules, and to copy and distribute the resulting executable under 031terms of your choice, provided that you also meet, for each linked 032independent module, the terms and conditions of the license of that 033module. An independent module is a module which is not derived from 034or based on this library. If you modify this library, you may extend 035this exception to your version of the library, but you are not 036obligated to do so. If you do not wish to do so, delete this 037exception statement from your version. */ 038 039package java.net; 040 041import gnu.classpath.SystemProperties; 042 043import gnu.java.net.PlainDatagramSocketImpl; 044import gnu.java.nio.DatagramChannelImpl; 045 046import java.io.IOException; 047import java.nio.channels.DatagramChannel; 048import java.nio.channels.IllegalBlockingModeException; 049 050 051/** 052 * Written using on-line Java Platform 1.2 API Specification, as well 053 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). 054 * Status: Believed complete and correct. 055 */ 056/** 057 * This class models a connectionless datagram socket that sends 058 * individual packets of data across the network. In the TCP/IP world, 059 * this means UDP. Datagram packets do not have guaranteed delivery, 060 * or any guarantee about the order the data will be received on the 061 * remote host. 062 * 063 * @author Aaron M. Renn (arenn@urbanophile.com) 064 * @author Warren Levy (warrenl@cygnus.com) 065 * @date May 3, 1999. 066 */ 067public class DatagramSocket 068{ 069 /** 070 * This is the user DatagramSocketImplFactory for this class. If this 071 * variable is null, a default factory is used. 072 */ 073 private static DatagramSocketImplFactory factory; 074 075 /** 076 * This is the implementation object used by this socket. 077 */ 078 private DatagramSocketImpl impl; 079 080 /** 081 * True if socket implementation was created. 082 */ 083 private boolean implCreated; 084 085 /** 086 * This is the address we are "connected" to 087 */ 088 private InetAddress remoteAddress; 089 090 /** 091 * This is the port we are "connected" to 092 */ 093 private int remotePort = -1; 094 095 /** 096 * True if socket is bound. 097 */ 098 private boolean bound; 099 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 sm.checkConnect(address.getHostAddress(), port); 529 530 try 531 { 532 getImpl().connect(address, port); 533 remoteAddress = address; 534 remotePort = port; 535 } 536 catch (SocketException e) 537 { 538 // This means simply not connected or connect not implemented. 539 } 540 } 541 542 /** 543 * This method disconnects this socket from the address/port it was 544 * connected to. If the socket was not connected in the first place, 545 * this method does nothing. 546 * 547 * @since 1.2 548 */ 549 public void disconnect() 550 { 551 if (! isConnected()) 552 return; 553 554 try 555 { 556 getImpl().disconnect(); 557 } 558 catch (SocketException e) 559 { 560 // This cannot happen as we are connected. 561 } 562 finally 563 { 564 remoteAddress = null; 565 remotePort = -1; 566 } 567 } 568 569 /** 570 * Reads a datagram packet from the socket. Note that this method 571 * will block until a packet is received from the network. On return, 572 * the passed in <code>DatagramPacket</code> is populated with the data 573 * received and all the other information about the packet. 574 * 575 * @param p A <code>DatagramPacket</code> for storing the data 576 * 577 * @exception IOException If an error occurs. 578 * @exception SocketTimeoutException If setSoTimeout was previously called 579 * and the timeout has expired. 580 * @exception PortUnreachableException If the socket is connected to a 581 * currently unreachable destination. Note, there is no guarantee that the 582 * exception will be thrown. 583 * @exception IllegalBlockingModeException If this socket has an associated 584 * channel, and the channel is in non-blocking mode. 585 * @exception SecurityException If a security manager exists and its 586 * checkAccept method doesn't allow the receive. 587 */ 588 public synchronized void receive(DatagramPacket p) throws IOException 589 { 590 if (isClosed()) 591 throw new SocketException("socket is closed"); 592 593 if (remoteAddress != null && remoteAddress.isMulticastAddress()) 594 throw new IOException 595 ("Socket connected to a multicast address my not receive"); 596 597 if (getChannel() != null && ! getChannel().isBlocking() 598 && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 599 throw new IllegalBlockingModeException(); 600 601 DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen); 602 getImpl().receive(p2); 603 p.length = p2.length; 604 if (p2.getAddress() != null) 605 p.setAddress(p2.getAddress()); 606 if (p2.getPort() != -1) 607 p.setPort(p2.getPort()); 608 609 SecurityManager s = System.getSecurityManager(); 610 if (s != null && isConnected()) 611 s.checkAccept(p.getAddress().getHostAddress(), p.getPort()); 612 } 613 614 /** 615 * Sends the specified packet. The host and port to which the packet 616 * are to be sent should be set inside the packet. 617 * 618 * @param p The datagram packet to send. 619 * 620 * @exception IOException If an error occurs. 621 * @exception SecurityException If a security manager exists and its 622 * checkMulticast or checkConnect method doesn't allow the send. 623 * @exception PortUnreachableException If the socket is connected to a 624 * currently unreachable destination. Note, there is no guarantee that the 625 * exception will be thrown. 626 * @exception IllegalBlockingModeException If this socket has an associated 627 * channel, and the channel is in non-blocking mode. 628 */ 629 public void send(DatagramPacket p) throws IOException 630 { 631 if (isClosed()) 632 throw new SocketException("socket is closed"); 633 634 // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api. 635 SecurityManager s = System.getSecurityManager(); 636 if (s != null && ! isConnected()) 637 { 638 InetAddress addr = p.getAddress(); 639 if (addr.isMulticastAddress()) 640 s.checkMulticast(addr); 641 else 642 s.checkConnect(addr.getHostAddress(), p.getPort()); 643 } 644 645 if (isConnected()) 646 { 647 if (p.getAddress() != null 648 && (remoteAddress != p.getAddress() || remotePort != p.getPort())) 649 throw new IllegalArgumentException 650 ("DatagramPacket address does not match remote address"); 651 } 652 653 // FIXME: if this is a subclass of MulticastSocket, 654 // use getTimeToLive for TTL val. 655 if (getChannel() != null && ! getChannel().isBlocking() 656 && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 657 throw new IllegalBlockingModeException(); 658 659 getImpl().send(p); 660 } 661 662 /** 663 * Binds the socket to the given socket address. 664 * 665 * @param address The socket address to bind to. 666 * 667 * @exception SocketException If an error occurs. 668 * @exception SecurityException If a security manager exists and 669 * its checkListen method doesn't allow the operation. 670 * @exception IllegalArgumentException If address type is not supported. 671 * 672 * @since 1.4 673 */ 674 public void bind(SocketAddress address) throws SocketException 675 { 676 if (isClosed()) 677 throw new SocketException("socket is closed"); 678 679 if (address == null) 680 address = new InetSocketAddress(InetAddress.ANY_IF, 0); 681 682 if (! (address instanceof InetSocketAddress)) 683 throw new IllegalArgumentException("unsupported address type"); 684 685 InetAddress addr = ((InetSocketAddress) address).getAddress(); 686 int port = ((InetSocketAddress) address).getPort(); 687 688 if (port < 0 || port > 65535) 689 throw new IllegalArgumentException("Invalid port: " + port); 690 691 SecurityManager s = System.getSecurityManager(); 692 if (s != null) 693 s.checkListen(port); 694 695 if (addr == null) 696 addr = InetAddress.ANY_IF; 697 698 try 699 { 700 getImpl().bind(port, addr); 701 bound = true; 702 } 703 catch (SocketException exception) 704 { 705 getImpl().close(); 706 throw exception; 707 } 708 catch (RuntimeException exception) 709 { 710 getImpl().close(); 711 throw exception; 712 } 713 catch (Error error) 714 { 715 getImpl().close(); 716 throw error; 717 } 718 } 719 720 /** 721 * Checks if the datagram socket is closed. 722 * 723 * @return True if socket is closed, false otherwise. 724 * 725 * @since 1.4 726 */ 727 public boolean isClosed() 728 { 729 return impl == null; 730 } 731 732 /** 733 * Returns the datagram channel assoziated with this datagram socket. 734 * 735 * @return The associated <code>DatagramChannel</code> object or null 736 * 737 * @since 1.4 738 */ 739 public DatagramChannel getChannel() 740 { 741 return null; 742 } 743 744 /** 745 * Connects the datagram socket to a specified socket address. 746 * 747 * @param address The socket address to connect to. 748 * 749 * @exception SocketException If an error occurs. 750 * @exception IllegalArgumentException If address type is not supported. 751 * 752 * @since 1.4 753 */ 754 public void connect(SocketAddress address) throws SocketException 755 { 756 if (isClosed()) 757 throw new SocketException("socket is closed"); 758 759 if (! (address instanceof InetSocketAddress)) 760 throw new IllegalArgumentException("unsupported address type"); 761 762 InetSocketAddress tmp = (InetSocketAddress) address; 763 connect(tmp.getAddress(), tmp.getPort()); 764 } 765 766 /** 767 * Returns the binding state of the socket. 768 * 769 * @return True if socket bound, false otherwise. 770 * 771 * @since 1.4 772 */ 773 public boolean isBound() 774 { 775 return bound; 776 } 777 778 /** 779 * Returns the connection state of the socket. 780 * 781 * @return True if socket is connected, false otherwise. 782 * 783 * @since 1.4 784 */ 785 public boolean isConnected() 786 { 787 return remoteAddress != null; 788 } 789 790 /** 791 * Returns the SocketAddress of the host this socket is conneted to 792 * or null if this socket is not connected. 793 * 794 * @return The socket address of the remote host if connected or null 795 * 796 * @since 1.4 797 */ 798 public SocketAddress getRemoteSocketAddress() 799 { 800 if (! isConnected()) 801 return null; 802 803 return new InetSocketAddress(remoteAddress, remotePort); 804 } 805 806 /** 807 * Returns the local SocketAddress this socket is bound to. 808 * 809 * @return The local SocketAddress or null if the socket is not bound. 810 * 811 * @since 1.4 812 */ 813 public SocketAddress getLocalSocketAddress() 814 { 815 if (! isBound()) 816 return null; 817 818 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 819 } 820 821 /** 822 * Enables/Disables SO_REUSEADDR. 823 * 824 * @param on Whether or not to have SO_REUSEADDR turned on. 825 * 826 * @exception SocketException If an error occurs. 827 * 828 * @since 1.4 829 */ 830 public void setReuseAddress(boolean on) throws SocketException 831 { 832 if (isClosed()) 833 throw new SocketException("socket is closed"); 834 835 getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 836 } 837 838 /** 839 * Checks if SO_REUSEADDR is enabled. 840 * 841 * @return True if SO_REUSEADDR is set on the socket, false otherwise. 842 * 843 * @exception SocketException If an error occurs. 844 * 845 * @since 1.4 846 */ 847 public boolean getReuseAddress() throws SocketException 848 { 849 if (isClosed()) 850 throw new SocketException("socket is closed"); 851 852 Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR); 853 854 if (buf instanceof Boolean) 855 return ((Boolean) buf).booleanValue(); 856 857 throw new SocketException("unexpected type"); 858 } 859 860 /** 861 * Enables/Disables SO_BROADCAST 862 * 863 * @param enable True if SO_BROADCAST should be enabled, false otherwise. 864 * 865 * @exception SocketException If an error occurs 866 * 867 * @since 1.4 868 */ 869 public void setBroadcast(boolean enable) throws SocketException 870 { 871 if (isClosed()) 872 throw new SocketException("socket is closed"); 873 874 getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable)); 875 } 876 877 /** 878 * Checks if SO_BROADCAST is enabled 879 * 880 * @return Whether SO_BROADCAST is set 881 * 882 * @exception SocketException If an error occurs 883 * 884 * @since 1.4 885 */ 886 public boolean getBroadcast() throws SocketException 887 { 888 if (isClosed()) 889 throw new SocketException("socket is closed"); 890 891 Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST); 892 893 if (buf instanceof Boolean) 894 return ((Boolean) buf).booleanValue(); 895 896 throw new SocketException("unexpected type"); 897 } 898 899 /** 900 * Sets the traffic class value 901 * 902 * @param tc The traffic class 903 * 904 * @exception SocketException If an error occurs 905 * @exception IllegalArgumentException If tc value is illegal 906 * 907 * @see DatagramSocket#getTrafficClass() 908 * 909 * @since 1.4 910 */ 911 public void setTrafficClass(int tc) throws SocketException 912 { 913 if (isClosed()) 914 throw new SocketException("socket is closed"); 915 916 if (tc < 0 || tc > 255) 917 throw new IllegalArgumentException(); 918 919 getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc)); 920 } 921 922 /** 923 * Returns the current traffic class 924 * 925 * @return The current traffic class. 926 * 927 * @see DatagramSocket#setTrafficClass(int tc) 928 * 929 * @exception SocketException If an error occurs 930 * 931 * @since 1.4 932 */ 933 public int getTrafficClass() throws SocketException 934 { 935 if (isClosed()) 936 throw new SocketException("socket is closed"); 937 938 Object buf = getImpl().getOption(SocketOptions.IP_TOS); 939 940 if (buf instanceof Integer) 941 return ((Integer) buf).intValue(); 942 943 throw new SocketException("unexpected type"); 944 } 945 946 /** 947 * Sets the datagram socket implementation factory for the application 948 * 949 * @param fac The factory to set 950 * 951 * @exception IOException If an error occurs 952 * @exception SocketException If the factory is already defined 953 * @exception SecurityException If a security manager exists and its 954 * checkSetFactory method doesn't allow the operation 955 */ 956 public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 957 throws IOException 958 { 959 if (factory != null) 960 throw new SocketException("DatagramSocketImplFactory already defined"); 961 962 SecurityManager sm = System.getSecurityManager(); 963 if (sm != null) 964 sm.checkSetFactory(); 965 966 factory = fac; 967 } 968}