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