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.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.io.FileDescriptor; 33 34 import dalvik.annotation.optimization.ReachabilitySensitive; 35 import dalvik.system.BlockGuard; 36 import dalvik.system.CloseGuard; 37 import dalvik.system.SocketTagger; 38 import sun.net.ConnectionResetException; 39 import sun.net.NetHooks; 40 import sun.net.ResourceManager; 41 42 /** 43 * Default Socket Implementation. This implementation does 44 * not implement any security checks. 45 * Note this class should <b>NOT</b> be public. 46 * 47 * @author Steven B. Byrne 48 */ 49 abstract class AbstractPlainSocketImpl extends SocketImpl 50 { 51 /* instance variable for SO_TIMEOUT */ 52 int timeout; // timeout in millisec 53 // Android-removed: traffic class is set through socket 54 // private int trafficClass; 55 56 private boolean shut_rd = false; 57 private boolean shut_wr = false; 58 59 private SocketInputStream socketInputStream = null; 60 private SocketOutputStream socketOutputStream = null; 61 62 /* number of threads using the FileDescriptor */ 63 protected int fdUseCount = 0; 64 65 /* lock when increment/decrementing fdUseCount */ 66 // Android-added: @ReachabilitySensitive 67 // Marked mostly because it's used where fd is, and fd isn't declared here. 68 // This adds reachabilityFences where we would if fd were annotated. 69 @ReachabilitySensitive 70 protected final Object fdLock = new Object(); 71 72 /* indicates a close is pending on the file descriptor */ 73 protected boolean closePending = false; 74 75 /* indicates connection reset state */ 76 private int CONNECTION_NOT_RESET = 0; 77 private int CONNECTION_RESET_PENDING = 1; 78 private int CONNECTION_RESET = 2; 79 private int resetState; 80 private final Object resetLock = new Object(); 81 82 /* whether this Socket is a stream (TCP) socket or not (UDP) 83 */ 84 protected boolean stream; 85 86 // BEGIN Android-removed: Android doesn't need to load native net library 87 /* 88 /** 89 * Load net library into runtime. 90 * 91 static { 92 java.security.AccessController.doPrivileged( 93 new java.security.PrivilegedAction<Void>() { 94 public Void run() { 95 System.loadLibrary("net"); 96 return null; 97 } 98 }); 99 } 100 */ 101 // END Android-removed: Android doesn't need to load native net library 102 103 // Android-added: logs a warning if socket is not closed 104 @ReachabilitySensitive 105 private final CloseGuard guard = CloseGuard.get(); 106 107 /** 108 * Creates a socket with a boolean that specifies whether this 109 * is a stream socket (true) or an unconnected UDP socket (false). 110 */ 111 protected synchronized void create(boolean stream) throws IOException { 112 this.stream = stream; 113 if (!stream) { 114 ResourceManager.beforeUdpCreate(); 115 // Android-removed: socketCreate should set fd if it succeeds 116 // fd = new FileDescriptor(); 117 try { 118 socketCreate(false); 119 } catch (IOException ioe) { 120 ResourceManager.afterUdpClose(); 121 // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null. 122 // fd = null; 123 throw ioe; 124 } 125 } else { 126 // Android-removed: socketCreate should set fd if it succeeds 127 // fd = new FileDescriptor(); 128 socketCreate(true); 129 } 130 if (socket != null) 131 socket.setCreated(); 132 if (serverSocket != null) 133 serverSocket.setCreated(); 134 135 // Android-added: CloseGuard 136 if (fd != null && fd.valid()) { 137 guard.open("close"); 138 } 139 } 140 141 /** 142 * Creates a socket and connects it to the specified port on 143 * the specified host. 144 * @param host the specified host 145 * @param port the specified port 146 */ 147 protected void connect(String host, int port) 148 throws UnknownHostException, IOException 149 { 150 boolean connected = false; 151 try { 152 InetAddress address = InetAddress.getByName(host); 153 this.port = port; 154 this.address = address; 155 156 connectToAddress(address, port, timeout); 157 connected = true; 158 } finally { 159 if (!connected) { 160 try { 161 close(); 162 } catch (IOException ioe) { 163 /* Do nothing. If connect threw an exception then 164 it will be passed up the call stack */ 165 } 166 } 167 } 168 } 169 170 /** 171 * Creates a socket and connects it to the specified address on 172 * the specified port. 173 * @param address the address 174 * @param port the specified port 175 */ 176 protected void connect(InetAddress address, int port) throws IOException { 177 this.port = port; 178 this.address = address; 179 180 try { 181 connectToAddress(address, port, timeout); 182 return; 183 } catch (IOException e) { 184 // everything failed 185 close(); 186 throw e; 187 } 188 } 189 190 /** 191 * Creates a socket and connects it to the specified address on 192 * the specified port. 193 * @param address the address 194 * @param timeout the timeout value in milliseconds, or zero for no timeout. 195 * @throws IOException if connection fails 196 * @throws IllegalArgumentException if address is null or is a 197 * SocketAddress subclass not supported by this socket 198 * @since 1.4 199 */ 200 protected void connect(SocketAddress address, int timeout) 201 throws IOException { 202 boolean connected = false; 203 try { 204 if (address == null || !(address instanceof InetSocketAddress)) 205 throw new IllegalArgumentException("unsupported address type"); 206 InetSocketAddress addr = (InetSocketAddress) address; 207 if (addr.isUnresolved()) 208 throw new UnknownHostException(addr.getHostName()); 209 this.port = addr.getPort(); 210 this.address = addr.getAddress(); 211 212 connectToAddress(this.address, port, timeout); 213 connected = true; 214 } finally { 215 if (!connected) { 216 try { 217 close(); 218 } catch (IOException ioe) { 219 /* Do nothing. If connect threw an exception then 220 it will be passed up the call stack */ 221 } 222 } 223 } 224 } 225 226 private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { 227 if (address.isAnyLocalAddress()) { 228 doConnect(InetAddress.getLocalHost(), port, timeout); 229 } else { 230 doConnect(address, port, timeout); 231 } 232 } 233 234 public void setOption(int opt, Object val) throws SocketException { 235 if (isClosedOrPending()) { 236 throw new SocketException("Socket Closed"); 237 } 238 // BEGIN Android-removed: Logic dealing with value type moved to socketSetOption. 239 /* 240 boolean on = true; 241 switch (opt) { 242 /* check type safety b4 going native. These should never 243 * fail, since only java.Socket* has access to 244 * PlainSocketImpl.setOption(). 245 * 246 case SO_LINGER: 247 if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) 248 throw new SocketException("Bad parameter for option"); 249 if (val instanceof Boolean) { 250 /* true only if disabling - enabling should be Integer * 251 on = false; 252 } 253 break; 254 case SO_TIMEOUT: 255 if (val == null || (!(val instanceof Integer))) 256 throw new SocketException("Bad parameter for SO_TIMEOUT"); 257 int tmp = ((Integer) val).intValue(); 258 if (tmp < 0) 259 throw new IllegalArgumentException("timeout < 0"); 260 timeout = tmp; 261 break; 262 case IP_TOS: 263 if (val == null || !(val instanceof Integer)) { 264 throw new SocketException("bad argument for IP_TOS"); 265 } 266 trafficClass = ((Integer)val).intValue(); 267 break; 268 case SO_BINDADDR: 269 throw new SocketException("Cannot re-bind socket"); 270 case TCP_NODELAY: 271 if (val == null || !(val instanceof Boolean)) 272 throw new SocketException("bad parameter for TCP_NODELAY"); 273 on = ((Boolean)val).booleanValue(); 274 break; 275 case SO_SNDBUF: 276 case SO_RCVBUF: 277 if (val == null || !(val instanceof Integer) || 278 !(((Integer)val).intValue() > 0)) { 279 throw new SocketException("bad parameter for SO_SNDBUF " + 280 "or SO_RCVBUF"); 281 } 282 break; 283 case SO_KEEPALIVE: 284 if (val == null || !(val instanceof Boolean)) 285 throw new SocketException("bad parameter for SO_KEEPALIVE"); 286 on = ((Boolean)val).booleanValue(); 287 break; 288 case SO_OOBINLINE: 289 if (val == null || !(val instanceof Boolean)) 290 throw new SocketException("bad parameter for SO_OOBINLINE"); 291 on = ((Boolean)val).booleanValue(); 292 break; 293 case SO_REUSEADDR: 294 if (val == null || !(val instanceof Boolean)) 295 throw new SocketException("bad parameter for SO_REUSEADDR"); 296 on = ((Boolean)val).booleanValue(); 297 break; 298 default: 299 throw new SocketException("unrecognized TCP option: " + opt); 300 } 301 socketSetOption(opt, on, val); 302 */ 303 // END Android-removed: Logic dealing with value type moved to socketSetOption. 304 // Android-added: Keep track of timeout value not handled by socketSetOption 305 if (opt == SO_TIMEOUT) { 306 timeout = (Integer) val; 307 } 308 socketSetOption(opt, val); 309 } 310 public Object getOption(int opt) throws SocketException { 311 if (isClosedOrPending()) { 312 throw new SocketException("Socket Closed"); 313 } 314 if (opt == SO_TIMEOUT) { 315 return new Integer(timeout); 316 } 317 // BEGIN Android-changed: Logic dealing with value type moved to socketGetOption. 318 /* 319 int ret = 0; 320 /* 321 * The native socketGetOption() knows about 3 options. 322 * The 32 bit value it returns will be interpreted according 323 * to what we're asking. A return of -1 means it understands 324 * the option but its turned off. It will raise a SocketException 325 * if "opt" isn't one it understands. 326 * 327 328 switch (opt) { 329 case TCP_NODELAY: 330 ret = socketGetOption(opt, null); 331 return Boolean.valueOf(ret != -1); 332 case SO_OOBINLINE: 333 ret = socketGetOption(opt, null); 334 return Boolean.valueOf(ret != -1); 335 case SO_LINGER: 336 ret = socketGetOption(opt, null); 337 return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret)); 338 case SO_REUSEADDR: 339 ret = socketGetOption(opt, null); 340 return Boolean.valueOf(ret != -1); 341 case SO_BINDADDR: 342 InetAddressContainer in = new InetAddressContainer(); 343 ret = socketGetOption(opt, in); 344 return in.addr; 345 case SO_SNDBUF: 346 case SO_RCVBUF: 347 ret = socketGetOption(opt, null); 348 return new Integer(ret); 349 case IP_TOS: 350 try { 351 ret = socketGetOption(opt, null); 352 if (ret == -1) { // ipv6 tos 353 return trafficClass; 354 } else { 355 return ret; 356 } 357 } catch (SocketException se) { 358 // TODO - should make better effort to read TOS or TCLASS 359 return trafficClass; // ipv6 tos 360 } 361 case SO_KEEPALIVE: 362 ret = socketGetOption(opt, null); 363 return Boolean.valueOf(ret != -1); 364 // should never get here 365 default: 366 return null; 367 } 368 */ 369 return socketGetOption(opt); 370 // END Android-changed: Logic dealing with value type moved to socketGetOption. 371 } 372 373 /** 374 * The workhorse of the connection operation. Tries several times to 375 * establish a connection to the given <host, port>. If unsuccessful, 376 * throws an IOException indicating what went wrong. 377 */ 378 379 synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { 380 synchronized (fdLock) { 381 if (!closePending && (socket == null || !socket.isBound())) { 382 NetHooks.beforeTcpConnect(fd, address, port); 383 } 384 } 385 try { 386 acquireFD(); 387 try { 388 // Android-added: BlockGuard 389 BlockGuard.getThreadPolicy().onNetwork(); 390 socketConnect(address, port, timeout); 391 /* socket may have been closed during poll/select */ 392 synchronized (fdLock) { 393 if (closePending) { 394 throw new SocketException ("Socket closed"); 395 } 396 } 397 // If we have a ref. to the Socket, then sets the flags 398 // created, bound & connected to true. 399 // This is normally done in Socket.connect() but some 400 // subclasses of Socket may call impl.connect() directly! 401 if (socket != null) { 402 socket.setBound(); 403 socket.setConnected(); 404 } 405 } finally { 406 releaseFD(); 407 } 408 } catch (IOException e) { 409 close(); 410 throw e; 411 } 412 } 413 414 /** 415 * Binds the socket to the specified address of the specified local port. 416 * @param address the address 417 * @param lport the port 418 */ 419 protected synchronized void bind(InetAddress address, int lport) 420 throws IOException 421 { 422 synchronized (fdLock) { 423 if (!closePending && (socket == null || !socket.isBound())) { 424 NetHooks.beforeTcpBind(fd, address, lport); 425 } 426 } 427 socketBind(address, lport); 428 if (socket != null) 429 socket.setBound(); 430 if (serverSocket != null) 431 serverSocket.setBound(); 432 } 433 434 /** 435 * Listens, for a specified amount of time, for connections. 436 * @param count the amount of time to listen for connections 437 */ 438 protected synchronized void listen(int count) throws IOException { 439 socketListen(count); 440 } 441 442 /** 443 * Accepts connections. 444 * @param s the connection 445 */ 446 protected void accept(SocketImpl s) throws IOException { 447 acquireFD(); 448 try { 449 // Android-added: BlockGuard 450 BlockGuard.getThreadPolicy().onNetwork(); 451 socketAccept(s); 452 } finally { 453 releaseFD(); 454 } 455 } 456 457 /** 458 * Gets an InputStream for this socket. 459 */ 460 protected synchronized InputStream getInputStream() throws IOException { 461 synchronized (fdLock) { 462 if (isClosedOrPending()) 463 throw new IOException("Socket Closed"); 464 if (shut_rd) 465 throw new IOException("Socket input is shutdown"); 466 if (socketInputStream == null) 467 socketInputStream = new SocketInputStream(this); 468 } 469 return socketInputStream; 470 } 471 472 void setInputStream(SocketInputStream in) { 473 socketInputStream = in; 474 } 475 476 /** 477 * Gets an OutputStream for this socket. 478 */ 479 protected synchronized OutputStream getOutputStream() throws IOException { 480 synchronized (fdLock) { 481 if (isClosedOrPending()) 482 throw new IOException("Socket Closed"); 483 if (shut_wr) 484 throw new IOException("Socket output is shutdown"); 485 if (socketOutputStream == null) 486 socketOutputStream = new SocketOutputStream(this); 487 } 488 return socketOutputStream; 489 } 490 491 void setFileDescriptor(FileDescriptor fd) { 492 this.fd = fd; 493 } 494 495 void setAddress(InetAddress address) { 496 this.address = address; 497 } 498 499 void setPort(int port) { 500 this.port = port; 501 } 502 503 void setLocalPort(int localport) { 504 this.localport = localport; 505 } 506 507 /** 508 * Returns the number of bytes that can be read without blocking. 509 */ 510 protected synchronized int available() throws IOException { 511 if (isClosedOrPending()) { 512 throw new IOException("Stream closed."); 513 } 514 515 /* 516 * If connection has been reset or shut down for input, then return 0 517 * to indicate there are no buffered bytes. 518 */ 519 if (isConnectionReset() || shut_rd) { 520 return 0; 521 } 522 523 /* 524 * If no bytes available and we were previously notified 525 * of a connection reset then we move to the reset state. 526 * 527 * If are notified of a connection reset then check 528 * again if there are bytes buffered on the socket. 529 */ 530 int n = 0; 531 try { 532 n = socketAvailable(); 533 if (n == 0 && isConnectionResetPending()) { 534 setConnectionReset(); 535 } 536 } catch (ConnectionResetException exc1) { 537 setConnectionResetPending(); 538 try { 539 n = socketAvailable(); 540 if (n == 0) { 541 setConnectionReset(); 542 } 543 } catch (ConnectionResetException exc2) { 544 } 545 } 546 return n; 547 } 548 549 /** 550 * Closes the socket. 551 */ 552 protected void close() throws IOException { 553 synchronized(fdLock) { 554 if (fd != null && fd.valid()) { 555 if (!stream) { 556 ResourceManager.afterUdpClose(); 557 } 558 // Android-changed: 559 // Socket should be untagged before the preclose. After preclose, 560 // socket will dup2-ed to marker_fd, therefore, it won't describe the same file. 561 // If closingPending is true, then the socket has been preclosed. 562 // 563 // Also, close the CloseGuard when the #close is called. 564 if (!closePending) { 565 closePending = true; 566 guard.close(); 567 568 if (fdUseCount == 0) { 569 /* 570 * We close the FileDescriptor in two-steps - first the 571 * "pre-close" which closes the socket but doesn't 572 * release the underlying file descriptor. This operation 573 * may be lengthy due to untransmitted data and a long 574 * linger interval. Once the pre-close is done we do the 575 * actual socket to release the fd. 576 */ 577 try { 578 socketPreClose(); 579 } finally { 580 socketClose(); 581 } 582 // Android-changed(http://b/26470377): Some Android code doesn't expect file 583 // descriptor to be null. socketClose invalidates the fd by closing the fd. 584 // fd = null; 585 return; 586 } else { 587 /* 588 * If a thread has acquired the fd and a close 589 * isn't pending then use a deferred close. 590 * Also decrement fdUseCount to signal the last 591 * thread that releases the fd to close it. 592 */ 593 fdUseCount--; 594 socketPreClose(); 595 } 596 } 597 } 598 } 599 } 600 601 void reset() throws IOException { 602 if (fd != null && fd.valid()) { 603 socketClose(); 604 // Android-changed: Notified the CloseGuard object as the fd has been released. 605 guard.close(); 606 } 607 // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null. 608 // fd = null; 609 super.reset(); 610 } 611 612 613 /** 614 * Shutdown read-half of the socket connection; 615 */ 616 protected void shutdownInput() throws IOException { 617 // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null. 618 if (fd != null && fd.valid()) { 619 socketShutdown(SHUT_RD); 620 if (socketInputStream != null) { 621 socketInputStream.setEOF(true); 622 } 623 shut_rd = true; 624 } 625 } 626 627 /** 628 * Shutdown write-half of the socket connection; 629 */ 630 protected void shutdownOutput() throws IOException { 631 // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null. 632 if (fd != null && fd.valid()) { 633 socketShutdown(SHUT_WR); 634 shut_wr = true; 635 } 636 } 637 638 protected boolean supportsUrgentData () { 639 return true; 640 } 641 642 protected void sendUrgentData (int data) throws IOException { 643 // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null. 644 if (fd == null || !fd.valid()) { 645 throw new IOException("Socket Closed"); 646 } 647 socketSendUrgentData (data); 648 } 649 650 /** 651 * Cleans up if the user forgets to close it. 652 */ 653 protected void finalize() throws IOException { 654 // Android-added: CloseGuard 655 if (guard != null) { 656 guard.warnIfOpen(); 657 } 658 659 close(); 660 } 661 662 /* 663 * "Acquires" and returns the FileDescriptor for this impl 664 * 665 * A corresponding releaseFD is required to "release" the 666 * FileDescriptor. 667 */ 668 FileDescriptor acquireFD() { 669 synchronized (fdLock) { 670 fdUseCount++; 671 return fd; 672 } 673 } 674 675 /* 676 * "Release" the FileDescriptor for this impl. 677 * 678 * If the use count goes to -1 then the socket is closed. 679 */ 680 void releaseFD() { 681 synchronized (fdLock) { 682 fdUseCount--; 683 if (fdUseCount == -1) { 684 if (fd != null) { 685 try { 686 socketClose(); 687 } catch (IOException e) { 688 // Android-removed: b/26470377 Some Android code doesn't expect file 689 // descriptor to be null. socketClose invalidates the fd by closing the fd. 690 // } finally { 691 // fd = null; 692 } 693 } 694 } 695 } 696 } 697 698 public boolean isConnectionReset() { 699 synchronized (resetLock) { 700 return (resetState == CONNECTION_RESET); 701 } 702 } 703 704 public boolean isConnectionResetPending() { 705 synchronized (resetLock) { 706 return (resetState == CONNECTION_RESET_PENDING); 707 } 708 } 709 710 public void setConnectionReset() { 711 synchronized (resetLock) { 712 resetState = CONNECTION_RESET; 713 } 714 } 715 716 public void setConnectionResetPending() { 717 synchronized (resetLock) { 718 if (resetState == CONNECTION_NOT_RESET) { 719 resetState = CONNECTION_RESET_PENDING; 720 } 721 } 722 723 } 724 725 /* 726 * Return true if already closed or close is pending 727 */ 728 public boolean isClosedOrPending() { 729 /* 730 * Lock on fdLock to ensure that we wait if a 731 * close is in progress. 732 */ 733 synchronized (fdLock) { 734 // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null. 735 if (closePending || (fd == null) || !fd.valid()) { 736 return true; 737 } else { 738 return false; 739 } 740 } 741 } 742 743 /* 744 * Return the current value of SO_TIMEOUT 745 */ 746 public int getTimeout() { 747 return timeout; 748 } 749 750 /* 751 * "Pre-close" a socket by dup'ing the file descriptor - this enables 752 * the socket to be closed without releasing the file descriptor. 753 */ 754 private void socketPreClose() throws IOException { 755 socketClose0(true); 756 } 757 758 /* 759 * Close the socket (and release the file descriptor). 760 */ 761 protected void socketClose() throws IOException { 762 socketClose0(false); 763 } 764 765 abstract void socketCreate(boolean isServer) throws IOException; 766 abstract void socketConnect(InetAddress address, int port, int timeout) 767 throws IOException; 768 abstract void socketBind(InetAddress address, int port) 769 throws IOException; 770 abstract void socketListen(int count) 771 throws IOException; 772 abstract void socketAccept(SocketImpl s) 773 throws IOException; 774 abstract int socketAvailable() 775 throws IOException; 776 abstract void socketClose0(boolean useDeferredClose) 777 throws IOException; 778 abstract void socketShutdown(int howto) 779 throws IOException; 780 781 // Android-changed: Method signature changed, socket{Get,Set}Option work directly with Object 782 // values. 783 abstract void socketSetOption(int cmd, Object value) throws SocketException; 784 abstract Object socketGetOption(int opt) throws SocketException; 785 786 abstract void socketSendUrgentData(int data) 787 throws IOException; 788 789 public final static int SHUT_RD = 0; 790 public final static int SHUT_WR = 1; 791 } 792