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