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