1 /* 2 * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import java.io.IOException; 29 import java.nio.channels.DatagramChannel; 30 import java.security.AccessController; 31 import java.security.PrivilegedExceptionAction; 32 import java.util.Objects; 33 import java.util.Set; 34 import java.util.Collections; 35 36 /** 37 * This class represents a socket for sending and receiving datagram packets. 38 * 39 * <p>A datagram socket is the sending or receiving point for a packet 40 * delivery service. Each packet sent or received on a datagram socket 41 * is individually addressed and routed. Multiple packets sent from 42 * one machine to another may be routed differently, and may arrive in 43 * any order. 44 * 45 * <p> Where possible, a newly constructed {@code DatagramSocket} has the 46 * {@link StandardSocketOptions#SO_BROADCAST SO_BROADCAST} socket option enabled so as 47 * to allow the transmission of broadcast datagrams. In order to receive 48 * broadcast packets a DatagramSocket should be bound to the wildcard address. 49 * In some implementations, broadcast packets may also be received when 50 * a DatagramSocket is bound to a more specific address. 51 * <p> 52 * Example: 53 * <pre>{@code 54 * DatagramSocket s = new DatagramSocket(null); 55 * s.bind(new InetSocketAddress(8888)); 56 * }</pre> 57 * Which is equivalent to: 58 * <pre>{@code 59 * DatagramSocket s = new DatagramSocket(8888); 60 * }</pre> 61 * Both cases will create a DatagramSocket able to receive broadcasts on 62 * UDP port 8888. 63 * 64 * <p> The {@code DatagramSocket} class defines convenience 65 * methods to set and get several socket options. This class also 66 * defines the {@link #setOption(SocketOption,Object) setOption} 67 * and {@link #getOption(SocketOption) getOption} methods to set 68 * and query socket options. 69 * A {@code DatagramSocket} supports the following socket options: 70 * <blockquote> 71 * <a id="SocketOptions"></a> 72 * <table class="striped"> 73 * <caption style="display:none">Socket options</caption> 74 * <thead> 75 * <tr> 76 * <th scope="col">Option Name</th> 77 * <th scope="col">Description</th> 78 * </tr> 79 * </thead> 80 * <tbody> 81 * <tr> 82 * <th scope="row"> {@link java.net.StandardSocketOptions#SO_SNDBUF SO_SNDBUF} </th> 83 * <td> The size of the socket send buffer </td> 84 * </tr> 85 * <tr> 86 * <th scope="row"> {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} </th> 87 * <td> The size of the socket receive buffer </td> 88 * </tr> 89 * <tr> 90 * <th scope="row"> {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} </th> 91 * <td> Re-use address </td> 92 * </tr> 93 * <tr> 94 * <th scope="row"> {@link java.net.StandardSocketOptions#SO_BROADCAST SO_BROADCAST} </th> 95 * <td> Allow transmission of broadcast datagrams </td> 96 * </tr> 97 * <tr> 98 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_TOS IP_TOS} </th> 99 * <td> The Type of Service (ToS) octet in the Internet Protocol (IP) header </td> 100 * </tr> 101 * </tbody> 102 * </table> 103 * </blockquote> 104 * An implementation may also support additional options. In particular an implementation 105 * may support <a href="MulticastSocket.html#MulticastOptions">multicast options</a> which 106 * can be useful when using a plain {@code DatagramSocket} to send datagrams to a 107 * multicast group. 108 * 109 * @author Pavani Diwanji 110 * @see java.net.DatagramPacket 111 * @see java.nio.channels.DatagramChannel 112 * @since 1.0 113 */ 114 public class DatagramSocket implements java.io.Closeable { 115 /** 116 * Various states of this socket. 117 */ 118 private boolean bound = false; 119 private boolean closed = false; 120 private Object closeLock = new Object(); 121 122 /* 123 * The implementation of this DatagramSocket. 124 */ 125 private final DatagramSocketImpl impl; 126 127 /** 128 * Are we using an older DatagramSocketImpl? 129 */ 130 boolean oldImpl = false; 131 132 /** 133 * Set when a socket is ST_CONNECTED until we are certain 134 * that any packets which might have been received prior 135 * to calling connect() but not read by the application 136 * have been read. During this time we check the source 137 * address of all packets received to be sure they are from 138 * the connected destination. Other packets are read but 139 * silently dropped. 140 */ 141 private boolean explicitFilter = false; 142 private int bytesLeftToFilter; 143 /* 144 * Connection state: 145 * ST_NOT_CONNECTED = socket not connected 146 * ST_CONNECTED = socket connected 147 * ST_CONNECTED_NO_IMPL = socket connected but not at impl level 148 */ 149 static final int ST_NOT_CONNECTED = 0; 150 static final int ST_CONNECTED = 1; 151 static final int ST_CONNECTED_NO_IMPL = 2; 152 153 int connectState = ST_NOT_CONNECTED; 154 155 /* 156 * Connected address & port 157 */ 158 InetAddress connectedAddress = null; 159 int connectedPort = -1; 160 161 /** 162 * Connects this socket to a remote socket address (IP address + port number). 163 * Binds socket if not already bound. 164 * 165 * @param address The remote address. 166 * @param port The remote port 167 * @throws SocketException if binding the socket fails. 168 */ 169 private synchronized void connectInternal(InetAddress address, int port) throws SocketException { 170 if (port < 0 || port > 0xFFFF) { 171 throw new IllegalArgumentException("connect: " + port); 172 } 173 if (address == null) { 174 throw new IllegalArgumentException("connect: null address"); 175 } 176 checkAddress (address, "connect"); 177 if (isClosed()) 178 return; 179 SecurityManager security = System.getSecurityManager(); 180 if (security != null) { 181 if (address.isMulticastAddress()) { 182 security.checkMulticast(address); 183 } else { 184 security.checkConnect(address.getHostAddress(), port); 185 security.checkAccept(address.getHostAddress(), port); 186 } 187 } 188 189 if (!isBound()) 190 bind(new InetSocketAddress(0)); 191 192 // old impls do not support connect/disconnect 193 if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl && 194 ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) { 195 connectState = ST_CONNECTED_NO_IMPL; 196 } else { 197 try { 198 getImpl().connect(address, port); 199 200 // socket is now connected by the impl 201 connectState = ST_CONNECTED; 202 // Do we need to filter some packets? 203 int avail = getImpl().dataAvailable(); 204 if (avail == -1) { 205 throw new SocketException(); 206 } 207 explicitFilter = avail > 0; 208 if (explicitFilter) { 209 bytesLeftToFilter = getReceiveBufferSize(); 210 } 211 } catch (SocketException se) { 212 213 // connection will be emulated by DatagramSocket 214 connectState = ST_CONNECTED_NO_IMPL; 215 } 216 } 217 218 connectedAddress = address; 219 connectedPort = port; 220 } 221 222 223 /** 224 * Constructs a datagram socket and binds it to any available port 225 * on the local host machine. The socket will be bound to the 226 * {@link InetAddress#isAnyLocalAddress wildcard} address, 227 * an IP address chosen by the kernel. 228 * 229 * <p>If there is a security manager, 230 * its {@code checkListen} method is first called 231 * with 0 as its argument to ensure the operation is allowed. 232 * This could result in a SecurityException. 233 * 234 * @throws SocketException if the socket could not be opened, 235 * or the socket could not bind to the specified local port. 236 * @throws SecurityException if a security manager exists and its 237 * {@code checkListen} method doesn't allow the operation. 238 * 239 * @see SecurityManager#checkListen 240 */ 241 public DatagramSocket() throws SocketException { 242 this(new InetSocketAddress(0)); 243 } 244 245 /** 246 * Creates an unbound datagram socket with the specified 247 * DatagramSocketImpl. 248 * 249 * @param impl an instance of a <B>DatagramSocketImpl</B> 250 * the subclass wishes to use on the DatagramSocket. 251 * @since 1.4 252 */ 253 protected DatagramSocket(DatagramSocketImpl impl) { 254 if (impl == null) 255 throw new NullPointerException(); 256 this.impl = impl; 257 checkOldImpl(); 258 } 259 260 /** 261 * Creates a datagram socket, bound to the specified local 262 * socket address. 263 * <p> 264 * If, if the address is {@code null}, creates an unbound socket. 265 * 266 * <p>If there is a security manager, 267 * its {@code checkListen} method is first called 268 * with the port from the socket address 269 * as its argument to ensure the operation is allowed. 270 * This could result in a SecurityException. 271 * 272 * @param bindaddr local socket address to bind, or {@code null} 273 * for an unbound socket. 274 * 275 * @throws SocketException if the socket could not be opened, 276 * or the socket could not bind to the specified local port. 277 * @throws SecurityException if a security manager exists and its 278 * {@code checkListen} method doesn't allow the operation. 279 * 280 * @see SecurityManager#checkListen 281 * @since 1.4 282 */ 283 public DatagramSocket(SocketAddress bindaddr) throws SocketException { 284 // Special case initialization for the DatagramChannel socket adaptor. 285 if (this instanceof sun.nio.ch.DatagramSocketAdaptor) { 286 this.impl = null; // no DatagramSocketImpl 287 return; 288 } 289 290 // create a datagram socket. 291 boolean multicast = (this instanceof MulticastSocket); 292 this.impl = createImpl(multicast); 293 checkOldImpl(); 294 if (bindaddr != null) { 295 try { 296 bind(bindaddr); 297 } finally { 298 if (!isBound()) 299 close(); 300 } 301 } 302 } 303 304 /** 305 * Constructs a datagram socket and binds it to the specified port 306 * on the local host machine. The socket will be bound to the 307 * {@link InetAddress#isAnyLocalAddress wildcard} address, 308 * an IP address chosen by the kernel. 309 * 310 * <p>If there is a security manager, 311 * its {@code checkListen} method is first called 312 * with the {@code port} argument 313 * as its argument to ensure the operation is allowed. 314 * This could result in a SecurityException. 315 * 316 * @param port port to use. 317 * @throws SocketException if the socket could not be opened, 318 * or the socket could not bind to the specified local port. 319 * @throws SecurityException if a security manager exists and its 320 * {@code checkListen} method doesn't allow the operation. 321 * 322 * @see SecurityManager#checkListen 323 */ 324 public DatagramSocket(int port) throws SocketException { 325 this(port, null); 326 } 327 328 /** 329 * Creates a datagram socket, bound to the specified local 330 * address. The local port must be between 0 and 65535 inclusive. 331 * If the IP address is 0.0.0.0, the socket will be bound to the 332 * {@link InetAddress#isAnyLocalAddress wildcard} address, 333 * an IP address chosen by the kernel. 334 * 335 * <p>If there is a security manager, 336 * its {@code checkListen} method is first called 337 * with the {@code port} argument 338 * as its argument to ensure the operation is allowed. 339 * This could result in a SecurityException. 340 * 341 * @param port local port to use 342 * @param laddr local address to bind 343 * 344 * @throws SocketException if the socket could not be opened, 345 * or the socket could not bind to the specified local port. 346 * @throws SecurityException if a security manager exists and its 347 * {@code checkListen} method doesn't allow the operation. 348 * 349 * @see SecurityManager#checkListen 350 * @since 1.1 351 */ 352 public DatagramSocket(int port, InetAddress laddr) throws SocketException { 353 this(new InetSocketAddress(laddr, port)); 354 } 355 356 private void checkOldImpl() { 357 if (impl == null) 358 return; 359 // DatagramSocketImpl.peekData() is a protected method, therefore we need to use 360 // getDeclaredMethod, therefore we need permission to access the member 361 try { 362 AccessController.doPrivileged( 363 new PrivilegedExceptionAction<>() { 364 public Void run() throws NoSuchMethodException { 365 Class<?>[] cl = new Class<?>[1]; 366 cl[0] = DatagramPacket.class; 367 impl.getClass().getDeclaredMethod("peekData", cl); 368 return null; 369 } 370 }); 371 } catch (java.security.PrivilegedActionException e) { 372 oldImpl = true; 373 } 374 } 375 376 static Class<?> implClass = null; 377 378 /** 379 * Creates a DatagramSocketImpl. 380 * @param multicast true if the DatagramSocketImpl is for a MulticastSocket 381 */ 382 private static DatagramSocketImpl createImpl(boolean multicast) throws SocketException { 383 DatagramSocketImpl impl; 384 DatagramSocketImplFactory factory = DatagramSocket.factory; 385 if (factory != null) { 386 impl = factory.createDatagramSocketImpl(); 387 } else { 388 impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast); 389 } 390 // creates a udp socket 391 impl.create(); 392 return impl; 393 } 394 395 /** 396 * Return the {@code DatagramSocketImpl} attached to this socket. 397 * 398 * @return the {@code DatagramSocketImpl} attached to that 399 * DatagramSocket 400 * @throws SocketException never thrown 401 * @since 1.4 402 */ 403 DatagramSocketImpl getImpl() throws SocketException { 404 return impl; 405 } 406 407 /** 408 * Binds this DatagramSocket to a specific address and port. 409 * <p> 410 * If the address is {@code null}, then the system will pick up 411 * an ephemeral port and a valid local address to bind the socket. 412 * 413 * @param addr The address and port to bind to. 414 * @throws SocketException if any error happens during the bind, or if the 415 * socket is already bound. 416 * @throws SecurityException if a security manager exists and its 417 * {@code checkListen} method doesn't allow the operation. 418 * @throws IllegalArgumentException if addr is a SocketAddress subclass 419 * not supported by this socket. 420 * @since 1.4 421 */ 422 public synchronized void bind(SocketAddress addr) throws SocketException { 423 if (isClosed()) 424 throw new SocketException("Socket is closed"); 425 if (isBound()) 426 throw new SocketException("already bound"); 427 if (addr == null) 428 addr = new InetSocketAddress(0); 429 if (!(addr instanceof InetSocketAddress)) 430 throw new IllegalArgumentException("Unsupported address type!"); 431 InetSocketAddress epoint = (InetSocketAddress) addr; 432 if (epoint.isUnresolved()) 433 throw new SocketException("Unresolved address"); 434 InetAddress iaddr = epoint.getAddress(); 435 int port = epoint.getPort(); 436 checkAddress(iaddr, "bind"); 437 SecurityManager sec = System.getSecurityManager(); 438 if (sec != null) { 439 sec.checkListen(port); 440 } 441 try { 442 getImpl().bind(port, iaddr); 443 } catch (SocketException e) { 444 getImpl().close(); 445 throw e; 446 } 447 bound = true; 448 } 449 450 void checkAddress (InetAddress addr, String op) { 451 if (addr == null) { 452 return; 453 } 454 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { 455 throw new IllegalArgumentException(op + ": invalid address type"); 456 } 457 } 458 459 /** 460 * Connects the socket to a remote address for this socket. When a 461 * socket is connected to a remote address, packets may only be 462 * sent to or received from that address. By default a datagram 463 * socket is not connected. 464 * 465 * <p>If the remote destination to which the socket is connected does not 466 * exist, or is otherwise unreachable, and if an ICMP destination unreachable 467 * packet has been received for that address, then a subsequent call to 468 * send or receive may throw a PortUnreachableException. Note, there is no 469 * guarantee that the exception will be thrown. 470 * 471 * <p> If a security manager has been installed then it is invoked to check 472 * access to the remote address. Specifically, if the given {@code address} 473 * is a {@link InetAddress#isMulticastAddress multicast address}, 474 * the security manager's {@link 475 * java.lang.SecurityManager#checkMulticast(InetAddress) 476 * checkMulticast} method is invoked with the given {@code address}. 477 * Otherwise, the security manager's {@link 478 * java.lang.SecurityManager#checkConnect(String,int) checkConnect} 479 * and {@link java.lang.SecurityManager#checkAccept checkAccept} methods 480 * are invoked, with the given {@code address} and {@code port}, to 481 * verify that datagrams are permitted to be sent and received 482 * respectively. 483 * 484 * <p> Care should be taken to ensure that a connected datagram socket 485 * is not shared with untrusted code. When a socket is connected, 486 * {@link #receive receive} and {@link #send send} <b>will not perform 487 * any security checks</b> on incoming and outgoing packets, other than 488 * matching the packet's and the socket's address and port. On a send 489 * operation, if the packet's address is set and the packet's address 490 * and the socket's address do not match, an {@code IllegalArgumentException} 491 * will be thrown. A socket connected to a multicast address may only 492 * be used to send packets. 493 * 494 * @param address the remote address for the socket 495 * 496 * @param port the remote port for the socket. 497 * 498 * @throws IllegalArgumentException 499 * if the address is null, or the port is out of range. 500 * 501 * @throws SecurityException 502 * if a security manager has been installed and it does 503 * not permit access to the given remote address 504 * 505 * @see #disconnect 506 */ 507 public void connect(InetAddress address, int port) { 508 try { 509 connectInternal(address, port); 510 } catch (SocketException se) { 511 throw new Error("connect failed", se); 512 } 513 } 514 515 /** 516 * Connects this socket to a remote socket address (IP address + port number). 517 * 518 * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method 519 * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)} 520 * with the given socket addresses IP address and port number. 521 * 522 * @param addr The remote address. 523 * 524 * @throws SocketException 525 * if the connect fails 526 * 527 * @throws IllegalArgumentException 528 * if {@code addr} is {@code null}, or {@code addr} is a SocketAddress 529 * subclass not supported by this socket 530 * 531 * @throws SecurityException 532 * if a security manager has been installed and it does 533 * not permit access to the given remote address 534 * 535 * @since 1.4 536 */ 537 public void connect(SocketAddress addr) throws SocketException { 538 if (addr == null) 539 throw new IllegalArgumentException("Address can't be null"); 540 if (!(addr instanceof InetSocketAddress)) 541 throw new IllegalArgumentException("Unsupported address type"); 542 InetSocketAddress epoint = (InetSocketAddress) addr; 543 if (epoint.isUnresolved()) 544 throw new SocketException("Unresolved address"); 545 connectInternal(epoint.getAddress(), epoint.getPort()); 546 } 547 548 /** 549 * Disconnects the socket. If the socket is closed or not connected, 550 * then this method has no effect. 551 * 552 * @see #connect 553 */ 554 public void disconnect() { 555 synchronized (this) { 556 if (isClosed()) 557 return; 558 if (connectState == ST_CONNECTED) { 559 impl.disconnect (); 560 } 561 connectedAddress = null; 562 connectedPort = -1; 563 connectState = ST_NOT_CONNECTED; 564 explicitFilter = false; 565 } 566 } 567 568 /** 569 * Returns the binding state of the socket. 570 * <p> 571 * If the socket was bound prior to being {@link #close closed}, 572 * then this method will continue to return {@code true} 573 * after the socket is closed. 574 * 575 * @return true if the socket successfully bound to an address 576 * @since 1.4 577 */ 578 public boolean isBound() { 579 return bound; 580 } 581 582 /** 583 * Returns the connection state of the socket. 584 * <p> 585 * If the socket was connected prior to being {@link #close closed}, 586 * then this method will continue to return {@code true} 587 * after the socket is closed. 588 * 589 * @return true if the socket successfully connected to a server 590 * @since 1.4 591 */ 592 public boolean isConnected() { 593 return connectState != ST_NOT_CONNECTED; 594 } 595 596 /** 597 * Returns the address to which this socket is connected. Returns 598 * {@code null} if the socket is not connected. 599 * <p> 600 * If the socket was connected prior to being {@link #close closed}, 601 * then this method will continue to return the connected address 602 * after the socket is closed. 603 * 604 * @return the address to which this socket is connected. 605 */ 606 public InetAddress getInetAddress() { 607 return connectedAddress; 608 } 609 610 /** 611 * Returns the port number to which this socket is connected. 612 * Returns {@code -1} if the socket is not connected. 613 * <p> 614 * If the socket was connected prior to being {@link #close closed}, 615 * then this method will continue to return the connected port number 616 * after the socket is closed. 617 * 618 * @return the port number to which this socket is connected. 619 */ 620 public int getPort() { 621 return connectedPort; 622 } 623 624 /** 625 * Returns the address of the endpoint this socket is connected to, or 626 * {@code null} if it is unconnected. 627 * <p> 628 * If the socket was connected prior to being {@link #close closed}, 629 * then this method will continue to return the connected address 630 * after the socket is closed. 631 * 632 * @return a {@code SocketAddress} representing the remote 633 * endpoint of this socket, or {@code null} if it is 634 * not connected yet. 635 * @see #getInetAddress() 636 * @see #getPort() 637 * @see #connect(SocketAddress) 638 * @since 1.4 639 */ 640 public SocketAddress getRemoteSocketAddress() { 641 if (!isConnected()) 642 return null; 643 return new InetSocketAddress(getInetAddress(), getPort()); 644 } 645 646 /** 647 * Returns the address of the endpoint this socket is bound to. 648 * 649 * @return a {@code SocketAddress} representing the local endpoint of this 650 * socket, or {@code null} if it is closed or not bound yet. 651 * @see #getLocalAddress() 652 * @see #getLocalPort() 653 * @see #bind(SocketAddress) 654 * @since 1.4 655 */ 656 public SocketAddress getLocalSocketAddress() { 657 if (isClosed()) 658 return null; 659 if (!isBound()) 660 return null; 661 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 662 } 663 664 /** 665 * Sends a datagram packet from this socket. The 666 * {@code DatagramPacket} includes information indicating the 667 * data to be sent, its length, the IP address of the remote host, 668 * and the port number on the remote host. 669 * 670 * <p>If there is a security manager, and the socket is not currently 671 * connected to a remote address, this method first performs some 672 * security checks. First, if {@code p.getAddress().isMulticastAddress()} 673 * is true, this method calls the 674 * security manager's {@code checkMulticast} method 675 * with {@code p.getAddress()} as its argument. 676 * If the evaluation of that expression is false, 677 * this method instead calls the security manager's 678 * {@code checkConnect} method with arguments 679 * {@code p.getAddress().getHostAddress()} and 680 * {@code p.getPort()}. Each call to a security manager method 681 * could result in a SecurityException if the operation is not allowed. 682 * 683 * @param p the {@code DatagramPacket} to be sent. 684 * 685 * @throws IOException if an I/O error occurs. 686 * @throws SecurityException if a security manager exists and its 687 * {@code checkMulticast} or {@code checkConnect} 688 * method doesn't allow the send. 689 * @throws PortUnreachableException may be thrown if the socket is connected 690 * to a currently unreachable destination. Note, there is no 691 * guarantee that the exception will be thrown. 692 * @throws java.nio.channels.IllegalBlockingModeException 693 * if this socket has an associated channel, 694 * and the channel is in non-blocking mode. 695 * @throws IllegalArgumentException if the socket is connected, 696 * and connected address and packet address differ, or 697 * if the socket is not connected and the packet address 698 * is not set. 699 * 700 * @see java.net.DatagramPacket 701 * @see SecurityManager#checkMulticast(InetAddress) 702 * @see SecurityManager#checkConnect 703 * @revised 1.4 704 * @spec JSR-51 705 */ 706 public void send(DatagramPacket p) throws IOException { 707 synchronized (p) { 708 if (isClosed()) 709 throw new SocketException("Socket is closed"); 710 InetAddress packetAddress = p.getAddress(); 711 checkAddress (packetAddress, "send"); 712 if (connectState == ST_NOT_CONNECTED) { 713 if (packetAddress == null) { 714 throw new IllegalArgumentException("Address not set"); 715 } 716 // check the address is ok with the security manager on every send. 717 SecurityManager security = System.getSecurityManager(); 718 719 // The reason you want to synchronize on datagram packet 720 // is because you don't want an applet to change the address 721 // while you are trying to send the packet for example 722 // after the security check but before the send. 723 if (security != null) { 724 if (packetAddress.isMulticastAddress()) { 725 security.checkMulticast(packetAddress); 726 } else { 727 security.checkConnect(packetAddress.getHostAddress(), 728 p.getPort()); 729 } 730 } 731 } else { 732 // we're connected 733 if (packetAddress == null) { 734 p.setAddress(connectedAddress); 735 p.setPort(connectedPort); 736 } else if ((!packetAddress.equals(connectedAddress)) || 737 p.getPort() != connectedPort) { 738 throw new IllegalArgumentException("connected address " + 739 "and packet address" + 740 " differ"); 741 } 742 } 743 // Check whether the socket is bound 744 if (!isBound()) 745 bind(new InetSocketAddress(0)); 746 // call the method to send 747 getImpl().send(p); 748 } 749 } 750 751 /** 752 * Receives a datagram packet from this socket. When this method 753 * returns, the {@code DatagramPacket}'s buffer is filled with 754 * the data received. The datagram packet also contains the sender's 755 * IP address, and the port number on the sender's machine. 756 * <p> 757 * This method blocks until a datagram is received. The 758 * {@code length} field of the datagram packet object contains 759 * the length of the received message. If the message is longer than 760 * the packet's length, the message is truncated. 761 * <p> 762 * If there is a security manager, and the socket is not currently 763 * connected to a remote address, a packet cannot be received if the 764 * security manager's {@code checkAccept} method does not allow it. 765 * Datagrams that are not permitted by the security manager are silently 766 * discarded. 767 * 768 * @param p the {@code DatagramPacket} into which to place 769 * the incoming data. 770 * @throws IOException if an I/O error occurs. 771 * @throws SocketTimeoutException if setSoTimeout was previously called 772 * and the timeout has expired. 773 * @throws PortUnreachableException may be thrown if the socket is connected 774 * to a currently unreachable destination. Note, there is no guarantee that the 775 * exception will be thrown. 776 * @throws java.nio.channels.IllegalBlockingModeException 777 * if this socket has an associated channel, 778 * and the channel is in non-blocking mode. 779 * @see java.net.DatagramPacket 780 * @see java.net.DatagramSocket 781 * @revised 1.4 782 * @spec JSR-51 783 */ 784 public synchronized void receive(DatagramPacket p) throws IOException { 785 synchronized (p) { 786 if (!isBound()) 787 bind(new InetSocketAddress(0)); 788 if (connectState == ST_NOT_CONNECTED) { 789 // check the address is ok with the security manager before every recv. 790 SecurityManager security = System.getSecurityManager(); 791 if (security != null) { 792 while(true) { 793 String peekAd = null; 794 int peekPort = 0; 795 // peek at the packet to see who it is from. 796 if (!oldImpl) { 797 // We can use the new peekData() API 798 DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); 799 peekPort = getImpl().peekData(peekPacket); 800 peekAd = peekPacket.getAddress().getHostAddress(); 801 } else { 802 InetAddress adr = new InetAddress(); 803 peekPort = getImpl().peek(adr); 804 peekAd = adr.getHostAddress(); 805 } 806 try { 807 security.checkAccept(peekAd, peekPort); 808 // security check succeeded - so now break 809 // and recv the packet. 810 break; 811 } catch (SecurityException se) { 812 // Throw away the offending packet by consuming 813 // it in a tmp buffer. 814 DatagramPacket tmp = new DatagramPacket(new byte[1], 1); 815 getImpl().receive(tmp); 816 817 // silently discard the offending packet 818 // and continue: unknown/malicious 819 // entities on nets should not make 820 // runtime throw security exception and 821 // disrupt the applet by sending random 822 // datagram packets. 823 continue; 824 } 825 } // end of while 826 } 827 } 828 DatagramPacket tmp = null; 829 if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) { 830 // We have to do the filtering the old fashioned way since 831 // the native impl doesn't support connect or the connect 832 // via the impl failed, or .. "explicitFilter" may be set when 833 // a socket is connected via the impl, for a period of time 834 // when packets from other sources might be queued on socket. 835 boolean stop = false; 836 while (!stop) { 837 InetAddress peekAddress = null; 838 int peekPort = -1; 839 // peek at the packet to see who it is from. 840 if (!oldImpl) { 841 // We can use the new peekData() API 842 DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); 843 peekPort = getImpl().peekData(peekPacket); 844 peekAddress = peekPacket.getAddress(); 845 } else { 846 // this api only works for IPv4 847 peekAddress = new InetAddress(); 848 peekPort = getImpl().peek(peekAddress); 849 } 850 if ((!connectedAddress.equals(peekAddress)) || 851 (connectedPort != peekPort)) { 852 // throw the packet away and silently continue 853 tmp = new DatagramPacket( 854 new byte[1024], 1024); 855 getImpl().receive(tmp); 856 if (explicitFilter) { 857 if (checkFiltering(tmp)) { 858 stop = true; 859 } 860 } 861 } else { 862 stop = true; 863 } 864 } 865 } 866 // If the security check succeeds, or the datagram is 867 // connected then receive the packet 868 getImpl().receive(p); 869 if (explicitFilter && tmp == null) { 870 // packet was not filtered, account for it here 871 checkFiltering(p); 872 } 873 } 874 } 875 876 private boolean checkFiltering(DatagramPacket p) throws SocketException { 877 bytesLeftToFilter -= p.getLength(); 878 if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) { 879 explicitFilter = false; 880 return true; 881 } 882 return false; 883 } 884 885 /** 886 * Gets the local address to which the socket is bound. 887 * 888 * <p>If there is a security manager, its 889 * {@code checkConnect} method is first called 890 * with the host address and {@code -1} 891 * as its arguments to see if the operation is allowed. 892 * 893 * @see SecurityManager#checkConnect 894 * @return the local address to which the socket is bound, 895 * {@code null} if the socket is closed, or 896 * an {@code InetAddress} representing 897 * {@link InetAddress#isAnyLocalAddress wildcard} 898 * address if either the socket is not bound, or 899 * the security manager {@code checkConnect} 900 * method does not allow the operation 901 * @since 1.1 902 */ 903 public InetAddress getLocalAddress() { 904 if (isClosed()) 905 return null; 906 InetAddress in; 907 try { 908 in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 909 if (in.isAnyLocalAddress()) { 910 in = InetAddress.anyLocalAddress(); 911 } 912 SecurityManager s = System.getSecurityManager(); 913 if (s != null) { 914 s.checkConnect(in.getHostAddress(), -1); 915 } 916 } catch (Exception e) { 917 in = InetAddress.anyLocalAddress(); // "0.0.0.0" 918 } 919 return in; 920 } 921 922 /** 923 * Returns the port number on the local host to which this socket 924 * is bound. 925 * 926 * @return the port number on the local host to which this socket is bound, 927 * {@code -1} if the socket is closed, or 928 * {@code 0} if it is not bound yet. 929 */ 930 public int getLocalPort() { 931 if (isClosed()) 932 return -1; 933 try { 934 return getImpl().getLocalPort(); 935 } catch (Exception e) { 936 return 0; 937 } 938 } 939 940 /** 941 * Enable/disable SO_TIMEOUT with the specified timeout, in 942 * milliseconds. With this option set to a positive timeout value, 943 * a call to receive() for this DatagramSocket 944 * will block for only this amount of time. If the timeout expires, 945 * a <B>java.net.SocketTimeoutException</B> is raised, though the 946 * DatagramSocket is still valid. A timeout of zero is interpreted 947 * as an infinite timeout. 948 * The option <B>must</B> be enabled prior to entering the blocking 949 * operation to have effect. 950 * 951 * @param timeout the specified timeout in milliseconds. 952 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. 953 * @throws IllegalArgumentException if {@code timeout} is negative 954 * @since 1.1 955 * @see #getSoTimeout() 956 */ 957 public synchronized void setSoTimeout(int timeout) throws SocketException { 958 if (isClosed()) 959 throw new SocketException("Socket is closed"); 960 if (timeout < 0) 961 throw new IllegalArgumentException("timeout < 0"); 962 getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout); 963 } 964 965 /** 966 * Retrieve setting for SO_TIMEOUT. 0 returns implies that the 967 * option is disabled (i.e., timeout of infinity). 968 * 969 * @return the setting for SO_TIMEOUT 970 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. 971 * @since 1.1 972 * @see #setSoTimeout(int) 973 */ 974 public synchronized int getSoTimeout() throws SocketException { 975 if (isClosed()) 976 throw new SocketException("Socket is closed"); 977 if (getImpl() == null) 978 return 0; 979 Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); 980 /* extra type safety */ 981 if (o instanceof Integer) { 982 return ((Integer) o).intValue(); 983 } else { 984 return 0; 985 } 986 } 987 988 /** 989 * Sets the SO_SNDBUF option to the specified value for this 990 * {@code DatagramSocket}. The SO_SNDBUF option is used by the 991 * network implementation as a hint to size the underlying 992 * network I/O buffers. The SO_SNDBUF setting may also be used 993 * by the network implementation to determine the maximum size 994 * of the packet that can be sent on this socket. 995 * <p> 996 * As SO_SNDBUF is a hint, applications that want to verify 997 * what size the buffer is should call {@link #getSendBufferSize()}. 998 * <p> 999 * Increasing the buffer size may allow multiple outgoing packets 1000 * to be queued by the network implementation when the send rate 1001 * is high. 1002 * <p> 1003 * Note: If {@link #send(DatagramPacket)} is used to send a 1004 * {@code DatagramPacket} that is larger than the setting 1005 * of SO_SNDBUF then it is implementation specific if the 1006 * packet is sent or discarded. 1007 * 1008 * @param size the size to which to set the send buffer 1009 * size. This value must be greater than 0. 1010 * 1011 * @throws SocketException if there is an error 1012 * in the underlying protocol, such as an UDP error. 1013 * @throws IllegalArgumentException if the value is 0 or is 1014 * negative. 1015 * @see #getSendBufferSize() 1016 */ 1017 public synchronized void setSendBufferSize(int size) throws SocketException { 1018 if (!(size > 0)) { 1019 throw new IllegalArgumentException("negative send size"); 1020 } 1021 if (isClosed()) 1022 throw new SocketException("Socket is closed"); 1023 getImpl().setOption(SocketOptions.SO_SNDBUF, size); 1024 } 1025 1026 /** 1027 * Get value of the SO_SNDBUF option for this {@code DatagramSocket}, that is the 1028 * buffer size used by the platform for output on this {@code DatagramSocket}. 1029 * 1030 * @return the value of the SO_SNDBUF option for this {@code DatagramSocket} 1031 * @throws SocketException if there is an error in 1032 * the underlying protocol, such as an UDP error. 1033 * @see #setSendBufferSize 1034 */ 1035 public synchronized int getSendBufferSize() throws SocketException { 1036 if (isClosed()) 1037 throw new SocketException("Socket is closed"); 1038 int result = 0; 1039 Object o = getImpl().getOption(SocketOptions.SO_SNDBUF); 1040 if (o instanceof Integer) { 1041 result = ((Integer)o).intValue(); 1042 } 1043 return result; 1044 } 1045 1046 /** 1047 * Sets the SO_RCVBUF option to the specified value for this 1048 * {@code DatagramSocket}. The SO_RCVBUF option is used by 1049 * the network implementation as a hint to size the underlying 1050 * network I/O buffers. The SO_RCVBUF setting may also be used 1051 * by the network implementation to determine the maximum size 1052 * of the packet that can be received on this socket. 1053 * <p> 1054 * Because SO_RCVBUF is a hint, applications that want to 1055 * verify what size the buffers were set to should call 1056 * {@link #getReceiveBufferSize()}. 1057 * <p> 1058 * Increasing SO_RCVBUF may allow the network implementation 1059 * to buffer multiple packets when packets arrive faster than 1060 * are being received using {@link #receive(DatagramPacket)}. 1061 * <p> 1062 * Note: It is implementation specific if a packet larger 1063 * than SO_RCVBUF can be received. 1064 * 1065 * @param size the size to which to set the receive buffer 1066 * size. This value must be greater than 0. 1067 * 1068 * @throws SocketException if there is an error in 1069 * the underlying protocol, such as an UDP error. 1070 * @throws IllegalArgumentException if the value is 0 or is 1071 * negative. 1072 * @see #getReceiveBufferSize() 1073 */ 1074 public synchronized void setReceiveBufferSize(int size) throws SocketException { 1075 if (size <= 0) { 1076 throw new IllegalArgumentException("invalid receive size"); 1077 } 1078 if (isClosed()) 1079 throw new SocketException("Socket is closed"); 1080 getImpl().setOption(SocketOptions.SO_RCVBUF, size); 1081 } 1082 1083 /** 1084 * Get value of the SO_RCVBUF option for this {@code DatagramSocket}, that is the 1085 * buffer size used by the platform for input on this {@code DatagramSocket}. 1086 * 1087 * @return the value of the SO_RCVBUF option for this {@code DatagramSocket} 1088 * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. 1089 * @see #setReceiveBufferSize(int) 1090 */ 1091 public synchronized int getReceiveBufferSize() throws SocketException { 1092 if (isClosed()) 1093 throw new SocketException("Socket is closed"); 1094 int result = 0; 1095 Object o = getImpl().getOption(SocketOptions.SO_RCVBUF); 1096 if (o instanceof Integer) { 1097 result = ((Integer)o).intValue(); 1098 } 1099 return result; 1100 } 1101 1102 /** 1103 * Enable/disable the SO_REUSEADDR socket option. 1104 * <p> 1105 * For UDP sockets it may be necessary to bind more than one 1106 * socket to the same socket address. This is typically for the 1107 * purpose of receiving multicast packets 1108 * (See {@link java.net.MulticastSocket}). The 1109 * {@code SO_REUSEADDR} socket option allows multiple 1110 * sockets to be bound to the same socket address if the 1111 * {@code SO_REUSEADDR} socket option is enabled prior 1112 * to binding the socket using {@link #bind(SocketAddress)}. 1113 * <p> 1114 * Note: This functionality is not supported by all existing platforms, 1115 * so it is implementation specific whether this option will be ignored 1116 * or not. However, if it is not supported then 1117 * {@link #getReuseAddress()} will always return {@code false}. 1118 * <p> 1119 * When a {@code DatagramSocket} is created the initial setting 1120 * of {@code SO_REUSEADDR} is disabled. 1121 * <p> 1122 * The behaviour when {@code SO_REUSEADDR} is enabled or 1123 * disabled after a socket is bound (See {@link #isBound()}) 1124 * is not defined. 1125 * 1126 * @param on whether to enable or disable the 1127 * @throws SocketException if an error occurs enabling or 1128 * disabling the {@code SO_REUSEADDR} socket option, 1129 * or the socket is closed. 1130 * @since 1.4 1131 * @see #getReuseAddress() 1132 * @see #bind(SocketAddress) 1133 * @see #isBound() 1134 * @see #isClosed() 1135 */ 1136 public synchronized void setReuseAddress(boolean on) throws SocketException { 1137 if (isClosed()) 1138 throw new SocketException("Socket is closed"); 1139 // Integer instead of Boolean for compatibility with older DatagramSocketImpl 1140 if (oldImpl) 1141 getImpl().setOption(SocketOptions.SO_REUSEADDR, on?-1:0); 1142 else 1143 getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 1144 } 1145 1146 /** 1147 * Tests if SO_REUSEADDR is enabled. 1148 * 1149 * @return a {@code boolean} indicating whether or not SO_REUSEADDR is enabled. 1150 * @throws SocketException if there is an error 1151 * in the underlying protocol, such as an UDP error. 1152 * @since 1.4 1153 * @see #setReuseAddress(boolean) 1154 */ 1155 public synchronized boolean getReuseAddress() throws SocketException { 1156 if (isClosed()) 1157 throw new SocketException("Socket is closed"); 1158 Object o = getImpl().getOption(SocketOptions.SO_REUSEADDR); 1159 return ((Boolean)o).booleanValue(); 1160 } 1161 1162 /** 1163 * Enable/disable SO_BROADCAST. 1164 * 1165 * <p> Some operating systems may require that the Java virtual machine be 1166 * started with implementation specific privileges to enable this option or 1167 * send broadcast datagrams. 1168 * 1169 * @param on 1170 * whether or not to have broadcast turned on. 1171 * 1172 * @throws SocketException 1173 * if there is an error in the underlying protocol, such as an UDP 1174 * error. 1175 * 1176 * @since 1.4 1177 * @see #getBroadcast() 1178 */ 1179 public synchronized void setBroadcast(boolean on) throws SocketException { 1180 if (isClosed()) 1181 throw new SocketException("Socket is closed"); 1182 getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(on)); 1183 } 1184 1185 /** 1186 * Tests if SO_BROADCAST is enabled. 1187 * @return a {@code boolean} indicating whether or not SO_BROADCAST is enabled. 1188 * @throws SocketException if there is an error 1189 * in the underlying protocol, such as an UDP error. 1190 * @since 1.4 1191 * @see #setBroadcast(boolean) 1192 */ 1193 public synchronized boolean getBroadcast() throws SocketException { 1194 if (isClosed()) 1195 throw new SocketException("Socket is closed"); 1196 return ((Boolean)(getImpl().getOption(SocketOptions.SO_BROADCAST))).booleanValue(); 1197 } 1198 1199 /** 1200 * Sets traffic class or type-of-service octet in the IP 1201 * datagram header for datagrams sent from this DatagramSocket. 1202 * As the underlying network implementation may ignore this 1203 * value applications should consider it a hint. 1204 * 1205 * <P> The tc <B>must</B> be in the range {@code 0 <= tc <= 1206 * 255} or an IllegalArgumentException will be thrown. 1207 * <p>Notes: 1208 * <p>For Internet Protocol v4 the value consists of an 1209 * {@code integer}, the least significant 8 bits of which 1210 * represent the value of the TOS octet in IP packets sent by 1211 * the socket. 1212 * RFC 1349 defines the TOS values as follows: 1213 * 1214 * <UL> 1215 * <LI><CODE>IPTOS_LOWCOST (0x02)</CODE></LI> 1216 * <LI><CODE>IPTOS_RELIABILITY (0x04)</CODE></LI> 1217 * <LI><CODE>IPTOS_THROUGHPUT (0x08)</CODE></LI> 1218 * <LI><CODE>IPTOS_LOWDELAY (0x10)</CODE></LI> 1219 * </UL> 1220 * The last low order bit is always ignored as this 1221 * corresponds to the MBZ (must be zero) bit. 1222 * <p> 1223 * Setting bits in the precedence field may result in a 1224 * SocketException indicating that the operation is not 1225 * permitted. 1226 * <p> 1227 * for Internet Protocol v6 {@code tc} is the value that 1228 * would be placed into the sin6_flowinfo field of the IP header. 1229 * 1230 * @param tc an {@code int} value for the bitset. 1231 * @throws SocketException if there is an error setting the 1232 * traffic class or type-of-service 1233 * @since 1.4 1234 * @see #getTrafficClass 1235 */ 1236 public synchronized void setTrafficClass(int tc) throws SocketException { 1237 if (tc < 0 || tc > 255) 1238 throw new IllegalArgumentException("tc is not in range 0 -- 255"); 1239 1240 if (isClosed()) 1241 throw new SocketException("Socket is closed"); 1242 try { 1243 getImpl().setOption(SocketOptions.IP_TOS, tc); 1244 } catch (SocketException se) { 1245 // not supported if socket already connected 1246 // Solaris returns error in such cases 1247 if(!isConnected()) 1248 throw se; 1249 } 1250 } 1251 1252 /** 1253 * Gets traffic class or type-of-service in the IP datagram 1254 * header for packets sent from this DatagramSocket. 1255 * <p> 1256 * As the underlying network implementation may ignore the 1257 * traffic class or type-of-service set using {@link #setTrafficClass(int)} 1258 * this method may return a different value than was previously 1259 * set using the {@link #setTrafficClass(int)} method on this 1260 * DatagramSocket. 1261 * 1262 * @return the traffic class or type-of-service already set 1263 * @throws SocketException if there is an error obtaining the 1264 * traffic class or type-of-service value. 1265 * @since 1.4 1266 * @see #setTrafficClass(int) 1267 */ 1268 public synchronized int getTrafficClass() throws SocketException { 1269 if (isClosed()) 1270 throw new SocketException("Socket is closed"); 1271 return ((Integer)(getImpl().getOption(SocketOptions.IP_TOS))).intValue(); 1272 } 1273 1274 /** 1275 * Closes this datagram socket. 1276 * <p> 1277 * Any thread currently blocked in {@link #receive} upon this socket 1278 * will throw a {@link SocketException}. 1279 * 1280 * <p> If this socket has an associated channel then the channel is closed 1281 * as well. 1282 * 1283 * @revised 1.4 1284 * @spec JSR-51 1285 */ 1286 public void close() { 1287 synchronized(closeLock) { 1288 if (isClosed()) 1289 return; 1290 impl.close(); 1291 closed = true; 1292 } 1293 } 1294 1295 /** 1296 * Returns whether the socket is closed or not. 1297 * 1298 * @return true if the socket has been closed 1299 * @since 1.4 1300 */ 1301 public boolean isClosed() { 1302 synchronized(closeLock) { 1303 return closed; 1304 } 1305 } 1306 1307 /** 1308 * Returns the unique {@link java.nio.channels.DatagramChannel} object 1309 * associated with this datagram socket, if any. 1310 * 1311 * <p> A datagram socket will have a channel if, and only if, the channel 1312 * itself was created via the {@link java.nio.channels.DatagramChannel#open 1313 * DatagramChannel.open} method. 1314 * 1315 * @return the datagram channel associated with this datagram socket, 1316 * or {@code null} if this socket was not created for a channel 1317 * 1318 * @since 1.4 1319 * @spec JSR-51 1320 */ 1321 public DatagramChannel getChannel() { 1322 return null; 1323 } 1324 1325 /** 1326 * User defined factory for all datagram sockets. 1327 */ 1328 private static volatile DatagramSocketImplFactory factory; 1329 1330 /** 1331 * Sets the datagram socket implementation factory for the 1332 * application. The factory can be specified only once. 1333 * <p> 1334 * When an application creates a new datagram socket, the socket 1335 * implementation factory's {@code createDatagramSocketImpl} method is 1336 * called to create the actual datagram socket implementation. 1337 * <p> 1338 * Passing {@code null} to the method is a no-op unless the factory 1339 * was already set. 1340 * 1341 * <p>If there is a security manager, this method first calls 1342 * the security manager's {@code checkSetFactory} method 1343 * to ensure the operation is allowed. 1344 * This could result in a SecurityException. 1345 * 1346 * @param fac the desired factory. 1347 * @throws IOException if an I/O error occurs when setting the 1348 * datagram socket factory. 1349 * @throws SocketException if the factory is already defined. 1350 * @throws SecurityException if a security manager exists and its 1351 * {@code checkSetFactory} method doesn't allow the operation. 1352 * @see java.net.DatagramSocketImplFactory#createDatagramSocketImpl() 1353 * @see SecurityManager#checkSetFactory 1354 * @since 1.3 1355 */ 1356 public static synchronized void 1357 setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 1358 throws IOException 1359 { 1360 if (factory != null) { 1361 throw new SocketException("factory already defined"); 1362 } 1363 SecurityManager security = System.getSecurityManager(); 1364 if (security != null) { 1365 security.checkSetFactory(); 1366 } 1367 factory = fac; 1368 } 1369 1370 /** 1371 * Sets the value of a socket option. 1372 * 1373 * @param <T> The type of the socket option value 1374 * @param name The socket option 1375 * @param value The value of the socket option. A value of {@code null} 1376 * may be valid for some options. 1377 * 1378 * @return this DatagramSocket 1379 * 1380 * @throws UnsupportedOperationException if the datagram socket 1381 * does not support the option. 1382 * 1383 * @throws IllegalArgumentException if the value is not valid for 1384 * the option. 1385 * 1386 * @throws IOException if an I/O error occurs, or if the socket is closed. 1387 * 1388 * @throws SecurityException if a security manager is set and if the socket 1389 * option requires a security permission and if the caller does 1390 * not have the required permission. 1391 * {@link java.net.StandardSocketOptions StandardSocketOptions} 1392 * do not require any security permission. 1393 * 1394 * @throws NullPointerException if name is {@code null} 1395 * 1396 * @since 9 1397 */ 1398 public <T> DatagramSocket setOption(SocketOption<T> name, T value) 1399 throws IOException 1400 { 1401 Objects.requireNonNull(name); 1402 if (isClosed()) 1403 throw new SocketException("Socket is closed"); 1404 getImpl().setOption(name, value); 1405 return this; 1406 } 1407 1408 /** 1409 * Returns the value of a socket option. 1410 * 1411 * @param <T> The type of the socket option value 1412 * @param name The socket option 1413 * 1414 * @return The value of the socket option. 1415 * 1416 * @throws UnsupportedOperationException if the datagram socket 1417 * does not support the option. 1418 * 1419 * @throws IOException if an I/O error occurs, or if the socket is closed. 1420 * 1421 * @throws NullPointerException if name is {@code null} 1422 * 1423 * @throws SecurityException if a security manager is set and if the socket 1424 * option requires a security permission and if the caller does 1425 * not have the required permission. 1426 * {@link java.net.StandardSocketOptions StandardSocketOptions} 1427 * do not require any security permission. 1428 * 1429 * @since 9 1430 */ 1431 public <T> T getOption(SocketOption<T> name) throws IOException { 1432 Objects.requireNonNull(name); 1433 if (isClosed()) 1434 throw new SocketException("Socket is closed"); 1435 return getImpl().getOption(name); 1436 } 1437 1438 private static Set<SocketOption<?>> options; 1439 private static boolean optionsSet = false; 1440 1441 /** 1442 * Returns a set of the socket options supported by this socket. 1443 * 1444 * This method will continue to return the set of options even after 1445 * the socket has been closed. 1446 * 1447 * @return A set of the socket options supported by this socket. This set 1448 * may be empty if the socket's DatagramSocketImpl cannot be created. 1449 * 1450 * @since 9 1451 */ 1452 public Set<SocketOption<?>> supportedOptions() { 1453 synchronized(DatagramSocket.class) { 1454 if (optionsSet) { 1455 return options; 1456 } 1457 try { 1458 DatagramSocketImpl impl = getImpl(); 1459 options = Collections.unmodifiableSet(impl.supportedOptions()); 1460 } catch (IOException e) { 1461 options = Collections.emptySet(); 1462 } 1463 optionsSet = true; 1464 return options; 1465 } 1466 } 1467 }