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