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