1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 2000, 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 sun.nio.ch; 28 29 import java.io.FileDescriptor; 30 import java.io.IOException; 31 import java.net.InetAddress; 32 import java.net.InetSocketAddress; 33 import java.net.ProtocolFamily; 34 import java.net.Socket; 35 import java.net.SocketAddress; 36 import java.net.SocketOption; 37 import java.net.StandardProtocolFamily; 38 import java.net.StandardSocketOptions; 39 import java.nio.ByteBuffer; 40 import java.nio.channels.AlreadyBoundException; 41 import java.nio.channels.AlreadyConnectedException; 42 import java.nio.channels.AsynchronousCloseException; 43 import java.nio.channels.ClosedChannelException; 44 import java.nio.channels.ConnectionPendingException; 45 import java.nio.channels.NoConnectionPendingException; 46 import java.nio.channels.NotYetConnectedException; 47 import java.nio.channels.SelectionKey; 48 import java.nio.channels.SocketChannel; 49 import java.nio.channels.spi.SelectorProvider; 50 import java.util.Collections; 51 import java.util.HashSet; 52 import java.util.Set; 53 54 import dalvik.annotation.optimization.ReachabilitySensitive; 55 import dalvik.system.BlockGuard; 56 import dalvik.system.CloseGuard; 57 import sun.net.ExtendedOptionsImpl; 58 import sun.net.NetHooks; 59 60 61 /** 62 * An implementation of SocketChannels 63 */ 64 65 class SocketChannelImpl 66 extends SocketChannel 67 implements SelChImpl 68 { 69 70 // Used to make native read and write calls 71 private static NativeDispatcher nd; 72 73 // Our file descriptor object 74 private final FileDescriptor fd; 75 76 // fd value needed for dev/poll. This value will remain valid 77 // even after the value in the file descriptor object has been set to -1 78 private final int fdVal; 79 80 // IDs of native threads doing reads and writes, for signalling 81 private volatile long readerThread = 0; 82 private volatile long writerThread = 0; 83 84 // Lock held by current reading or connecting thread 85 private final Object readLock = new Object(); 86 87 // Lock held by current writing or connecting thread 88 private final Object writeLock = new Object(); 89 90 // Lock held by any thread that modifies the state fields declared below 91 // DO NOT invoke a blocking I/O operation while holding this lock! 92 private final Object stateLock = new Object(); 93 94 // -- The following fields are protected by stateLock 95 96 // set true when exclusive binding is on and SO_REUSEADDR is emulated 97 private boolean isReuseAddress; 98 99 // State, increases monotonically 100 private static final int ST_UNINITIALIZED = -1; 101 private static final int ST_UNCONNECTED = 0; 102 private static final int ST_PENDING = 1; 103 private static final int ST_CONNECTED = 2; 104 private static final int ST_KILLPENDING = 3; 105 private static final int ST_KILLED = 4; 106 private int state = ST_UNINITIALIZED; 107 108 // Binding 109 private InetSocketAddress localAddress; 110 private InetSocketAddress remoteAddress; 111 112 // Input/Output open 113 private boolean isInputOpen = true; 114 private boolean isOutputOpen = true; 115 private boolean readyToConnect = false; 116 117 // Socket adaptor, created on demand 118 private Socket socket; 119 120 // -- End of fields protected by stateLock 121 122 // Android-added: CloseGuard support. 123 @ReachabilitySensitive 124 private final CloseGuard guard = CloseGuard.get(); 125 126 // Constructor for normal connecting sockets 127 // SocketChannelImpl(SelectorProvider sp)128 SocketChannelImpl(SelectorProvider sp) throws IOException { 129 super(sp); 130 this.fd = Net.socket(true); 131 this.fdVal = IOUtil.fdVal(fd); 132 this.state = ST_UNCONNECTED; 133 134 // Android-added: CloseGuard support. 135 // Net#socket will set |fd| if it succeeds. 136 if (fd != null && fd.valid()) { 137 guard.open("close"); 138 } 139 } 140 SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)141 SocketChannelImpl(SelectorProvider sp, 142 FileDescriptor fd, 143 boolean bound) 144 throws IOException 145 { 146 super(sp); 147 this.fd = fd; 148 this.fdVal = IOUtil.fdVal(fd); 149 this.state = ST_UNCONNECTED; 150 151 // Android-added: CloseGuard support. 152 if (fd != null && fd.valid()) { 153 guard.open("close"); 154 } 155 156 if (bound) 157 this.localAddress = Net.localAddress(fd); 158 } 159 160 // Constructor for sockets obtained from server sockets 161 // SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, InetSocketAddress remote)162 SocketChannelImpl(SelectorProvider sp, 163 FileDescriptor fd, InetSocketAddress remote) 164 throws IOException 165 { 166 super(sp); 167 this.fd = fd; 168 this.fdVal = IOUtil.fdVal(fd); 169 this.state = ST_CONNECTED; 170 this.localAddress = Net.localAddress(fd); 171 this.remoteAddress = remote; 172 // Android-added: CloseGuard support. 173 if (fd != null && fd.valid()) { 174 guard.open("close"); 175 } 176 } 177 socket()178 public Socket socket() { 179 synchronized (stateLock) { 180 if (socket == null) 181 socket = SocketAdaptor.create(this); 182 return socket; 183 } 184 } 185 186 @Override getLocalAddress()187 public SocketAddress getLocalAddress() throws IOException { 188 synchronized (stateLock) { 189 if (!isOpen()) 190 throw new ClosedChannelException(); 191 return Net.getRevealedLocalAddress(localAddress); 192 } 193 } 194 195 @Override getRemoteAddress()196 public SocketAddress getRemoteAddress() throws IOException { 197 synchronized (stateLock) { 198 if (!isOpen()) 199 throw new ClosedChannelException(); 200 return remoteAddress; 201 } 202 } 203 204 @Override setOption(SocketOption<T> name, T value)205 public <T> SocketChannel setOption(SocketOption<T> name, T value) 206 throws IOException 207 { 208 if (name == null) 209 throw new NullPointerException(); 210 if (!supportedOptions().contains(name)) 211 throw new UnsupportedOperationException("'" + name + "' not supported"); 212 213 synchronized (stateLock) { 214 if (!isOpen()) 215 throw new ClosedChannelException(); 216 217 if (name == StandardSocketOptions.IP_TOS) { 218 ProtocolFamily family = Net.isIPv6Available() ? 219 StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; 220 Net.setSocketOption(fd, family, name, value); 221 return this; 222 } 223 224 if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { 225 // SO_REUSEADDR emulated when using exclusive bind 226 isReuseAddress = (Boolean)value; 227 return this; 228 } 229 230 // no options that require special handling 231 Net.setSocketOption(fd, Net.UNSPEC, name, value); 232 return this; 233 } 234 } 235 236 @Override 237 @SuppressWarnings("unchecked") getOption(SocketOption<T> name)238 public <T> T getOption(SocketOption<T> name) 239 throws IOException 240 { 241 if (name == null) 242 throw new NullPointerException(); 243 if (!supportedOptions().contains(name)) 244 throw new UnsupportedOperationException("'" + name + "' not supported"); 245 246 synchronized (stateLock) { 247 if (!isOpen()) 248 throw new ClosedChannelException(); 249 250 if (name == StandardSocketOptions.SO_REUSEADDR && 251 Net.useExclusiveBind()) 252 { 253 // SO_REUSEADDR emulated when using exclusive bind 254 return (T)Boolean.valueOf(isReuseAddress); 255 } 256 257 // special handling for IP_TOS: always return 0 when IPv6 258 if (name == StandardSocketOptions.IP_TOS) { 259 ProtocolFamily family = Net.isIPv6Available() ? 260 StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; 261 return (T) Net.getSocketOption(fd, family, name); 262 } 263 264 // no options that require special handling 265 return (T) Net.getSocketOption(fd, Net.UNSPEC, name); 266 } 267 } 268 269 private static class DefaultOptionsHolder { 270 static final Set<SocketOption<?>> defaultOptions = defaultOptions(); 271 defaultOptions()272 private static Set<SocketOption<?>> defaultOptions() { 273 HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8); 274 set.add(StandardSocketOptions.SO_SNDBUF); 275 set.add(StandardSocketOptions.SO_RCVBUF); 276 set.add(StandardSocketOptions.SO_KEEPALIVE); 277 set.add(StandardSocketOptions.SO_REUSEADDR); 278 set.add(StandardSocketOptions.SO_LINGER); 279 set.add(StandardSocketOptions.TCP_NODELAY); 280 // additional options required by socket adaptor 281 set.add(StandardSocketOptions.IP_TOS); 282 set.add(ExtendedSocketOption.SO_OOBINLINE); 283 if (ExtendedOptionsImpl.flowSupported()) { 284 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); 285 } 286 return Collections.unmodifiableSet(set); 287 } 288 } 289 290 @Override supportedOptions()291 public final Set<SocketOption<?>> supportedOptions() { 292 return DefaultOptionsHolder.defaultOptions; 293 } 294 ensureReadOpen()295 private boolean ensureReadOpen() throws ClosedChannelException { 296 synchronized (stateLock) { 297 if (!isOpen()) 298 throw new ClosedChannelException(); 299 if (!isConnected()) 300 throw new NotYetConnectedException(); 301 if (!isInputOpen) 302 return false; 303 else 304 return true; 305 } 306 } 307 ensureWriteOpen()308 private void ensureWriteOpen() throws ClosedChannelException { 309 synchronized (stateLock) { 310 if (!isOpen()) 311 throw new ClosedChannelException(); 312 if (!isOutputOpen) 313 throw new ClosedChannelException(); 314 if (!isConnected()) 315 throw new NotYetConnectedException(); 316 } 317 } 318 readerCleanup()319 private void readerCleanup() throws IOException { 320 synchronized (stateLock) { 321 readerThread = 0; 322 if (state == ST_KILLPENDING) 323 kill(); 324 } 325 } 326 writerCleanup()327 private void writerCleanup() throws IOException { 328 synchronized (stateLock) { 329 writerThread = 0; 330 if (state == ST_KILLPENDING) 331 kill(); 332 } 333 } 334 read(ByteBuffer buf)335 public int read(ByteBuffer buf) throws IOException { 336 337 if (buf == null) 338 throw new NullPointerException(); 339 340 synchronized (readLock) { 341 if (!ensureReadOpen()) 342 return -1; 343 int n = 0; 344 try { 345 346 // Set up the interruption machinery; see 347 // AbstractInterruptibleChannel for details 348 // 349 begin(); 350 351 synchronized (stateLock) { 352 if (!isOpen()) { 353 // Either the current thread is already interrupted, so 354 // begin() closed the channel, or another thread closed the 355 // channel since we checked it a few bytecodes ago. In 356 // either case the value returned here is irrelevant since 357 // the invocation of end() in the finally block will throw 358 // an appropriate exception. 359 // 360 return 0; 361 362 } 363 364 // Save this thread so that it can be signalled on those 365 // platforms that require it 366 // 367 readerThread = NativeThread.current(); 368 } 369 370 // Between the previous test of isOpen() and the return of the 371 // IOUtil.read invocation below, this channel might be closed 372 // or this thread might be interrupted. We rely upon the 373 // implicit synchronization point in the kernel read() call to 374 // make sure that the right thing happens. In either case the 375 // implCloseSelectableChannel method is ultimately invoked in 376 // some other thread, so there are three possibilities: 377 // 378 // - implCloseSelectableChannel() invokes nd.preClose() 379 // before this thread invokes read(), in which case the 380 // read returns immediately with either EOF or an error, 381 // the latter of which will cause an IOException to be 382 // thrown. 383 // 384 // - implCloseSelectableChannel() invokes nd.preClose() after 385 // this thread is blocked in read(). On some operating 386 // systems (e.g., Solaris and Windows) this causes the read 387 // to return immediately with either EOF or an error 388 // indication. 389 // 390 // - implCloseSelectableChannel() invokes nd.preClose() after 391 // this thread is blocked in read() but the operating 392 // system (e.g., Linux) doesn't support preemptive close, 393 // so implCloseSelectableChannel() proceeds to signal this 394 // thread, thereby causing the read to return immediately 395 // with IOStatus.INTERRUPTED. 396 // 397 // In all three cases the invocation of end() in the finally 398 // clause will notice that the channel has been closed and 399 // throw an appropriate exception (AsynchronousCloseException 400 // or ClosedByInterruptException) if necessary. 401 // 402 // *There is A fourth possibility. implCloseSelectableChannel() 403 // invokes nd.preClose(), signals reader/writer thred and quickly 404 // moves on to nd.close() in kill(), which does a real close. 405 // Then a third thread accepts a new connection, opens file or 406 // whatever that causes the released "fd" to be recycled. All 407 // above happens just between our last isOpen() check and the 408 // next kernel read reached, with the recycled "fd". The solution 409 // is to postpone the real kill() if there is a reader or/and 410 // writer thread(s) over there "waiting", leave the cleanup/kill 411 // to the reader or writer thread. (the preClose() still happens 412 // so the connection gets cut off as usual). 413 // 414 // For socket channels there is the additional wrinkle that 415 // asynchronous shutdown works much like asynchronous close, 416 // except that the channel is shutdown rather than completely 417 // closed. This is analogous to the first two cases above, 418 // except that the shutdown operation plays the role of 419 // nd.preClose(). 420 for (;;) { 421 n = IOUtil.read(fd, buf, -1, nd); 422 if ((n == IOStatus.INTERRUPTED) && isOpen()) { 423 // The system call was interrupted but the channel 424 // is still open, so retry 425 continue; 426 } 427 return IOStatus.normalize(n); 428 } 429 430 } finally { 431 readerCleanup(); // Clear reader thread 432 // The end method, which is defined in our superclass 433 // AbstractInterruptibleChannel, resets the interruption 434 // machinery. If its argument is true then it returns 435 // normally; otherwise it checks the interrupt and open state 436 // of this channel and throws an appropriate exception if 437 // necessary. 438 // 439 // So, if we actually managed to do any I/O in the above try 440 // block then we pass true to the end method. We also pass 441 // true if the channel was in non-blocking mode when the I/O 442 // operation was initiated but no data could be transferred; 443 // this prevents spurious exceptions from being thrown in the 444 // rare event that a channel is closed or a thread is 445 // interrupted at the exact moment that a non-blocking I/O 446 // request is made. 447 // 448 end(n > 0 || (n == IOStatus.UNAVAILABLE)); 449 450 // Extra case for socket channels: Asynchronous shutdown 451 // 452 synchronized (stateLock) { 453 if ((n <= 0) && (!isInputOpen)) 454 return IOStatus.EOF; 455 } 456 457 assert IOStatus.check(n); 458 459 } 460 } 461 } 462 read(ByteBuffer[] dsts, int offset, int length)463 public long read(ByteBuffer[] dsts, int offset, int length) 464 throws IOException 465 { 466 if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) 467 throw new IndexOutOfBoundsException(); 468 synchronized (readLock) { 469 if (!ensureReadOpen()) 470 return -1; 471 long n = 0; 472 try { 473 begin(); 474 synchronized (stateLock) { 475 if (!isOpen()) 476 return 0; 477 readerThread = NativeThread.current(); 478 } 479 480 for (;;) { 481 n = IOUtil.read(fd, dsts, offset, length, nd); 482 if ((n == IOStatus.INTERRUPTED) && isOpen()) 483 continue; 484 return IOStatus.normalize(n); 485 } 486 } finally { 487 readerCleanup(); 488 end(n > 0 || (n == IOStatus.UNAVAILABLE)); 489 synchronized (stateLock) { 490 if ((n <= 0) && (!isInputOpen)) 491 return IOStatus.EOF; 492 } 493 assert IOStatus.check(n); 494 } 495 } 496 } 497 write(ByteBuffer buf)498 public int write(ByteBuffer buf) throws IOException { 499 if (buf == null) 500 throw new NullPointerException(); 501 synchronized (writeLock) { 502 ensureWriteOpen(); 503 int n = 0; 504 try { 505 begin(); 506 synchronized (stateLock) { 507 if (!isOpen()) 508 return 0; 509 writerThread = NativeThread.current(); 510 } 511 for (;;) { 512 n = IOUtil.write(fd, buf, -1, nd); 513 if ((n == IOStatus.INTERRUPTED) && isOpen()) 514 continue; 515 return IOStatus.normalize(n); 516 } 517 } finally { 518 writerCleanup(); 519 end(n > 0 || (n == IOStatus.UNAVAILABLE)); 520 synchronized (stateLock) { 521 if ((n <= 0) && (!isOutputOpen)) 522 throw new AsynchronousCloseException(); 523 } 524 assert IOStatus.check(n); 525 } 526 } 527 } 528 write(ByteBuffer[] srcs, int offset, int length)529 public long write(ByteBuffer[] srcs, int offset, int length) 530 throws IOException 531 { 532 if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) 533 throw new IndexOutOfBoundsException(); 534 synchronized (writeLock) { 535 ensureWriteOpen(); 536 long n = 0; 537 try { 538 begin(); 539 synchronized (stateLock) { 540 if (!isOpen()) 541 return 0; 542 writerThread = NativeThread.current(); 543 } 544 for (;;) { 545 n = IOUtil.write(fd, srcs, offset, length, nd); 546 if ((n == IOStatus.INTERRUPTED) && isOpen()) 547 continue; 548 return IOStatus.normalize(n); 549 } 550 } finally { 551 writerCleanup(); 552 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 553 synchronized (stateLock) { 554 if ((n <= 0) && (!isOutputOpen)) 555 throw new AsynchronousCloseException(); 556 } 557 assert IOStatus.check(n); 558 } 559 } 560 } 561 562 // package-private sendOutOfBandData(byte b)563 int sendOutOfBandData(byte b) throws IOException { 564 synchronized (writeLock) { 565 ensureWriteOpen(); 566 int n = 0; 567 try { 568 begin(); 569 synchronized (stateLock) { 570 if (!isOpen()) 571 return 0; 572 writerThread = NativeThread.current(); 573 } 574 for (;;) { 575 n = sendOutOfBandData(fd, b); 576 if ((n == IOStatus.INTERRUPTED) && isOpen()) 577 continue; 578 return IOStatus.normalize(n); 579 } 580 } finally { 581 writerCleanup(); 582 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 583 synchronized (stateLock) { 584 if ((n <= 0) && (!isOutputOpen)) 585 throw new AsynchronousCloseException(); 586 } 587 assert IOStatus.check(n); 588 } 589 } 590 } 591 implConfigureBlocking(boolean block)592 protected void implConfigureBlocking(boolean block) throws IOException { 593 IOUtil.configureBlocking(fd, block); 594 } 595 localAddress()596 public InetSocketAddress localAddress() { 597 synchronized (stateLock) { 598 return localAddress; 599 } 600 } 601 remoteAddress()602 public SocketAddress remoteAddress() { 603 synchronized (stateLock) { 604 return remoteAddress; 605 } 606 } 607 608 @Override bind(SocketAddress local)609 public SocketChannel bind(SocketAddress local) throws IOException { 610 synchronized (readLock) { 611 synchronized (writeLock) { 612 synchronized (stateLock) { 613 if (!isOpen()) 614 throw new ClosedChannelException(); 615 if (state == ST_PENDING) 616 throw new ConnectionPendingException(); 617 if (localAddress != null) 618 throw new AlreadyBoundException(); 619 InetSocketAddress isa = (local == null) ? 620 new InetSocketAddress(0) : Net.checkAddress(local); 621 SecurityManager sm = System.getSecurityManager(); 622 if (sm != null) { 623 sm.checkListen(isa.getPort()); 624 } 625 NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); 626 Net.bind(fd, isa.getAddress(), isa.getPort()); 627 localAddress = Net.localAddress(fd); 628 } 629 } 630 } 631 return this; 632 } 633 isConnected()634 public boolean isConnected() { 635 synchronized (stateLock) { 636 return (state == ST_CONNECTED); 637 } 638 } 639 isConnectionPending()640 public boolean isConnectionPending() { 641 synchronized (stateLock) { 642 return (state == ST_PENDING); 643 } 644 } 645 ensureOpenAndUnconnected()646 void ensureOpenAndUnconnected() throws IOException { // package-private 647 synchronized (stateLock) { 648 if (!isOpen()) 649 throw new ClosedChannelException(); 650 if (state == ST_CONNECTED) 651 throw new AlreadyConnectedException(); 652 if (state == ST_PENDING) 653 throw new ConnectionPendingException(); 654 } 655 } 656 connect(SocketAddress sa)657 public boolean connect(SocketAddress sa) throws IOException { 658 int localPort = 0; 659 660 synchronized (readLock) { 661 synchronized (writeLock) { 662 ensureOpenAndUnconnected(); 663 InetSocketAddress isa = Net.checkAddress(sa); 664 SecurityManager sm = System.getSecurityManager(); 665 if (sm != null) 666 sm.checkConnect(isa.getAddress().getHostAddress(), 667 isa.getPort()); 668 synchronized (blockingLock()) { 669 int n = 0; 670 try { 671 try { 672 begin(); 673 synchronized (stateLock) { 674 if (!isOpen()) { 675 return false; 676 } 677 // notify hook only if unbound 678 if (localAddress == null) { 679 NetHooks.beforeTcpConnect(fd, 680 isa.getAddress(), 681 isa.getPort()); 682 } 683 readerThread = NativeThread.current(); 684 } 685 for (;;) { 686 InetAddress ia = isa.getAddress(); 687 if (ia.isAnyLocalAddress()) 688 ia = InetAddress.getLocalHost(); 689 n = Net.connect(fd, 690 ia, 691 isa.getPort()); 692 if ( (n == IOStatus.INTERRUPTED) 693 && isOpen()) 694 continue; 695 break; 696 } 697 698 } finally { 699 readerCleanup(); 700 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 701 assert IOStatus.check(n); 702 } 703 } catch (IOException x) { 704 // If an exception was thrown, close the channel after 705 // invoking end() so as to avoid bogus 706 // AsynchronousCloseExceptions 707 close(); 708 throw x; 709 } 710 synchronized (stateLock) { 711 remoteAddress = isa; 712 if (n > 0) { 713 714 // Connection succeeded; disallow further 715 // invocation 716 state = ST_CONNECTED; 717 if (isOpen()) 718 localAddress = Net.localAddress(fd); 719 return true; 720 } 721 // If nonblocking and no exception then connection 722 // pending; disallow another invocation 723 if (!isBlocking()) { 724 state = ST_PENDING; 725 if (isOpen()) { 726 localAddress = Net.localAddress(fd); 727 } 728 } 729 } 730 } 731 return false; 732 } 733 } 734 } 735 finishConnect()736 public boolean finishConnect() throws IOException { 737 synchronized (readLock) { 738 synchronized (writeLock) { 739 synchronized (stateLock) { 740 if (!isOpen()) 741 throw new ClosedChannelException(); 742 if (state == ST_CONNECTED) 743 return true; 744 if (state != ST_PENDING) 745 throw new NoConnectionPendingException(); 746 } 747 int n = 0; 748 try { 749 try { 750 begin(); 751 synchronized (blockingLock()) { 752 synchronized (stateLock) { 753 if (!isOpen()) { 754 return false; 755 } 756 readerThread = NativeThread.current(); 757 } 758 759 BlockGuard.getThreadPolicy().onNetwork(); 760 if (!isBlocking()) { 761 for (;;) { 762 n = checkConnect(fd, false, 763 readyToConnect); 764 if ( (n == IOStatus.INTERRUPTED) 765 && isOpen()) 766 continue; 767 break; 768 } 769 } else { 770 for (;;) { 771 n = checkConnect(fd, true, 772 readyToConnect); 773 if (n == 0) { 774 // Loop in case of 775 // spurious notifications 776 continue; 777 } 778 if ( (n == IOStatus.INTERRUPTED) 779 && isOpen()) 780 continue; 781 break; 782 } 783 } 784 } 785 } finally { 786 synchronized (stateLock) { 787 readerThread = 0; 788 if (state == ST_KILLPENDING) { 789 kill(); 790 // poll()/getsockopt() does not report 791 // error (throws exception, with n = 0) 792 // on Linux platform after dup2 and 793 // signal-wakeup. Force n to 0 so the 794 // end() can throw appropriate exception 795 n = 0; 796 } 797 } 798 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 799 assert IOStatus.check(n); 800 } 801 } catch (IOException x) { 802 // If an exception was thrown, close the channel after 803 // invoking end() so as to avoid bogus 804 // AsynchronousCloseExceptions 805 close(); 806 throw x; 807 } 808 if (n > 0) { 809 synchronized (stateLock) { 810 state = ST_CONNECTED; 811 if (isOpen()) 812 localAddress = Net.localAddress(fd); 813 } 814 return true; 815 } 816 return false; 817 } 818 } 819 } 820 821 @Override shutdownInput()822 public SocketChannel shutdownInput() throws IOException { 823 synchronized (stateLock) { 824 if (!isOpen()) 825 throw new ClosedChannelException(); 826 if (!isConnected()) 827 throw new NotYetConnectedException(); 828 if (isInputOpen) { 829 Net.shutdown(fd, Net.SHUT_RD); 830 if (readerThread != 0) 831 NativeThread.signal(readerThread); 832 isInputOpen = false; 833 } 834 return this; 835 } 836 } 837 838 @Override shutdownOutput()839 public SocketChannel shutdownOutput() throws IOException { 840 synchronized (stateLock) { 841 if (!isOpen()) 842 throw new ClosedChannelException(); 843 if (!isConnected()) 844 throw new NotYetConnectedException(); 845 if (isOutputOpen) { 846 Net.shutdown(fd, Net.SHUT_WR); 847 if (writerThread != 0) 848 NativeThread.signal(writerThread); 849 isOutputOpen = false; 850 } 851 return this; 852 } 853 } 854 isInputOpen()855 public boolean isInputOpen() { 856 synchronized (stateLock) { 857 return isInputOpen; 858 } 859 } 860 isOutputOpen()861 public boolean isOutputOpen() { 862 synchronized (stateLock) { 863 return isOutputOpen; 864 } 865 } 866 867 // AbstractInterruptibleChannel synchronizes invocations of this method 868 // using AbstractInterruptibleChannel.closeLock, and also ensures that this 869 // method is only ever invoked once. Before we get to this method, isOpen 870 // (which is volatile) will have been set to false. 871 // implCloseSelectableChannel()872 protected void implCloseSelectableChannel() throws IOException { 873 synchronized (stateLock) { 874 isInputOpen = false; 875 isOutputOpen = false; 876 877 // Close the underlying file descriptor and dup it to a known fd 878 // that's already closed. This prevents other operations on this 879 // channel from using the old fd, which might be recycled in the 880 // meantime and allocated to an entirely different channel. 881 // 882 if (state != ST_KILLED) { 883 // Android-added: CloseGuard support. 884 guard.close(); 885 nd.preClose(fd); 886 } 887 888 // Signal native threads, if needed. If a target thread is not 889 // currently blocked in an I/O operation then no harm is done since 890 // the signal handler doesn't actually do anything. 891 // 892 if (readerThread != 0) 893 NativeThread.signal(readerThread); 894 895 if (writerThread != 0) 896 NativeThread.signal(writerThread); 897 898 // If this channel is not registered then it's safe to close the fd 899 // immediately since we know at this point that no thread is 900 // blocked in an I/O operation upon the channel and, since the 901 // channel is marked closed, no thread will start another such 902 // operation. If this channel is registered then we don't close 903 // the fd since it might be in use by a selector. In that case 904 // closing this channel caused its keys to be cancelled, so the 905 // last selector to deregister a key for this channel will invoke 906 // kill() to close the fd. 907 // 908 if (!isRegistered()) 909 kill(); 910 } 911 } 912 kill()913 public void kill() throws IOException { 914 synchronized (stateLock) { 915 if (state == ST_KILLED) 916 return; 917 if (state == ST_UNINITIALIZED) { 918 state = ST_KILLED; 919 return; 920 } 921 assert !isOpen() && !isRegistered(); 922 923 // Postpone the kill if there is a waiting reader 924 // or writer thread. See the comments in read() for 925 // more detailed explanation. 926 if (readerThread == 0 && writerThread == 0) { 927 nd.close(fd); 928 state = ST_KILLED; 929 } else { 930 state = ST_KILLPENDING; 931 } 932 } 933 } 934 finalize()935 protected void finalize() throws IOException { 936 if (guard != null) { 937 guard.warnIfOpen(); 938 } 939 // BEGIN Android-changed: Integrate upstream code from DatagramChannelImpl.finalize(). 940 // http://b/115296581 941 // close(); 942 // fd is null if constructor threw exception 943 if (fd != null) { 944 close(); 945 } 946 // END Android-changed: Integrate upstream code from DatagramChannelImpl.finalize(). 947 } 948 949 /** 950 * Translates native poll revent ops into a ready operation ops 951 */ translateReadyOps(int ops, int initialOps, SelectionKeyImpl sk)952 public boolean translateReadyOps(int ops, int initialOps, 953 SelectionKeyImpl sk) { 954 int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes 955 int oldOps = sk.nioReadyOps(); 956 int newOps = initialOps; 957 958 if ((ops & Net.POLLNVAL) != 0) { 959 // This should only happen if this channel is pre-closed while a 960 // selection operation is in progress 961 // ## Throw an error if this channel has not been pre-closed 962 return false; 963 } 964 965 if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) { 966 newOps = intOps; 967 sk.nioReadyOps(newOps); 968 // No need to poll again in checkConnect, 969 // the error will be detected there 970 readyToConnect = true; 971 return (newOps & ~oldOps) != 0; 972 } 973 974 if (((ops & Net.POLLIN) != 0) && 975 ((intOps & SelectionKey.OP_READ) != 0) && 976 (state == ST_CONNECTED)) 977 newOps |= SelectionKey.OP_READ; 978 979 if (((ops & Net.POLLCONN) != 0) && 980 ((intOps & SelectionKey.OP_CONNECT) != 0) && 981 ((state == ST_UNCONNECTED) || (state == ST_PENDING))) { 982 newOps |= SelectionKey.OP_CONNECT; 983 readyToConnect = true; 984 } 985 986 if (((ops & Net.POLLOUT) != 0) && 987 ((intOps & SelectionKey.OP_WRITE) != 0) && 988 (state == ST_CONNECTED)) 989 newOps |= SelectionKey.OP_WRITE; 990 991 sk.nioReadyOps(newOps); 992 return (newOps & ~oldOps) != 0; 993 } 994 translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk)995 public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { 996 return translateReadyOps(ops, sk.nioReadyOps(), sk); 997 } 998 translateAndSetReadyOps(int ops, SelectionKeyImpl sk)999 public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { 1000 return translateReadyOps(ops, 0, sk); 1001 } 1002 1003 // package-private poll(int events, long timeout)1004 int poll(int events, long timeout) throws IOException { 1005 assert Thread.holdsLock(blockingLock()) && !isBlocking(); 1006 1007 synchronized (readLock) { 1008 int n = 0; 1009 try { 1010 begin(); 1011 synchronized (stateLock) { 1012 if (!isOpen()) 1013 return 0; 1014 readerThread = NativeThread.current(); 1015 } 1016 n = Net.poll(fd, events, timeout); 1017 } finally { 1018 readerCleanup(); 1019 end(n > 0); 1020 } 1021 return n; 1022 } 1023 } 1024 1025 /** 1026 * Translates an interest operation set into a native poll event set 1027 */ translateAndSetInterestOps(int ops, SelectionKeyImpl sk)1028 public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { 1029 int newOps = 0; 1030 if ((ops & SelectionKey.OP_READ) != 0) 1031 newOps |= Net.POLLIN; 1032 if ((ops & SelectionKey.OP_WRITE) != 0) 1033 newOps |= Net.POLLOUT; 1034 if ((ops & SelectionKey.OP_CONNECT) != 0) 1035 newOps |= Net.POLLCONN; 1036 sk.selector.putEventOps(sk, newOps); 1037 } 1038 getFD()1039 public FileDescriptor getFD() { 1040 return fd; 1041 } 1042 getFDVal()1043 public int getFDVal() { 1044 return fdVal; 1045 } 1046 1047 @Override toString()1048 public String toString() { 1049 StringBuffer sb = new StringBuffer(); 1050 sb.append(this.getClass().getSuperclass().getName()); 1051 sb.append('['); 1052 if (!isOpen()) 1053 sb.append("closed"); 1054 else { 1055 synchronized (stateLock) { 1056 switch (state) { 1057 case ST_UNCONNECTED: 1058 sb.append("unconnected"); 1059 break; 1060 case ST_PENDING: 1061 sb.append("connection-pending"); 1062 break; 1063 case ST_CONNECTED: 1064 sb.append("connected"); 1065 if (!isInputOpen) 1066 sb.append(" ishut"); 1067 if (!isOutputOpen) 1068 sb.append(" oshut"); 1069 break; 1070 } 1071 InetSocketAddress addr = localAddress(); 1072 if (addr != null) { 1073 sb.append(" local="); 1074 sb.append(Net.getRevealedLocalAddressAsString(addr)); 1075 } 1076 if (remoteAddress() != null) { 1077 sb.append(" remote="); 1078 sb.append(remoteAddress().toString()); 1079 } 1080 } 1081 } 1082 sb.append(']'); 1083 return sb.toString(); 1084 } 1085 1086 1087 // -- Native methods -- 1088 checkConnect(FileDescriptor fd, boolean block, boolean ready)1089 private static native int checkConnect(FileDescriptor fd, 1090 boolean block, boolean ready) 1091 throws IOException; 1092 sendOutOfBandData(FileDescriptor fd, byte data)1093 private static native int sendOutOfBandData(FileDescriptor fd, byte data) 1094 throws IOException; 1095 1096 static { 1097 nd = new SocketDispatcher(); 1098 } 1099 1100 } 1101