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