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