Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java
38918 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.io.FileDescriptor;28import java.io.IOException;29import java.net.*;30import java.nio.ByteBuffer;31import java.nio.channels.*;32import java.nio.channels.spi.*;33import java.util.*;34import sun.net.NetHooks;35import sun.net.ExtendedOptionsImpl;36import sun.net.ExtendedOptionsHelper;373839/**40* An implementation of SocketChannels41*/4243class SocketChannelImpl44extends SocketChannel45implements SelChImpl46{4748// Used to make native read and write calls49private static NativeDispatcher nd;5051// Our file descriptor object52private final FileDescriptor fd;53private final int fdVal;5455// IDs of native threads doing reads and writes, for signalling56private volatile long readerThread = 0;57private volatile long writerThread = 0;5859// Lock held by current reading or connecting thread60private final Object readLock = new Object();6162// Lock held by current writing or connecting thread63private final Object writeLock = new Object();6465// Lock held by any thread that modifies the state fields declared below66// DO NOT invoke a blocking I/O operation while holding this lock!67private final Object stateLock = new Object();6869// -- The following fields are protected by stateLock7071// set true when exclusive binding is on and SO_REUSEADDR is emulated72private boolean isReuseAddress;7374// State, increases monotonically75private static final int ST_UNINITIALIZED = -1;76private static final int ST_UNCONNECTED = 0;77private static final int ST_PENDING = 1;78private static final int ST_CONNECTED = 2;79private static final int ST_KILLPENDING = 3;80private static final int ST_KILLED = 4;81private int state = ST_UNINITIALIZED;8283// Binding84private InetSocketAddress localAddress;85private InetSocketAddress remoteAddress;8687// Input/Output open88private boolean isInputOpen = true;89private boolean isOutputOpen = true;90private boolean readyToConnect = false;9192// Socket adaptor, created on demand93private Socket socket;9495// -- End of fields protected by stateLock969798// Constructor for normal connecting sockets99//100SocketChannelImpl(SelectorProvider sp) throws IOException {101super(sp);102this.fd = Net.socket(true);103this.fdVal = IOUtil.fdVal(fd);104this.state = ST_UNCONNECTED;105}106107SocketChannelImpl(SelectorProvider sp,108FileDescriptor fd,109boolean bound)110throws IOException111{112super(sp);113this.fd = fd;114this.fdVal = IOUtil.fdVal(fd);115this.state = ST_UNCONNECTED;116if (bound)117this.localAddress = Net.localAddress(fd);118}119120// Constructor for sockets obtained from server sockets121//122SocketChannelImpl(SelectorProvider sp,123FileDescriptor fd, InetSocketAddress remote)124throws IOException125{126super(sp);127this.fd = fd;128this.fdVal = IOUtil.fdVal(fd);129this.state = ST_CONNECTED;130this.localAddress = Net.localAddress(fd);131this.remoteAddress = remote;132}133134public Socket socket() {135synchronized (stateLock) {136if (socket == null)137socket = SocketAdaptor.create(this);138return socket;139}140}141142@Override143public SocketAddress getLocalAddress() throws IOException {144synchronized (stateLock) {145if (!isOpen())146throw new ClosedChannelException();147return Net.getRevealedLocalAddress(localAddress);148}149}150151@Override152public SocketAddress getRemoteAddress() throws IOException {153synchronized (stateLock) {154if (!isOpen())155throw new ClosedChannelException();156return remoteAddress;157}158}159160@Override161public <T> SocketChannel setOption(SocketOption<T> name, T value)162throws IOException163{164if (name == null)165throw new NullPointerException();166if (!supportedOptions().contains(name))167throw new UnsupportedOperationException("'" + name + "' not supported");168169synchronized (stateLock) {170if (!isOpen())171throw new ClosedChannelException();172173if (name == StandardSocketOptions.IP_TOS) {174ProtocolFamily family = Net.isIPv6Available() ?175StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;176Net.setSocketOption(fd, family, name, value);177return this;178}179180if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {181// SO_REUSEADDR emulated when using exclusive bind182isReuseAddress = (Boolean)value;183return this;184}185186// no options that require special handling187Net.setSocketOption(fd, Net.UNSPEC, name, value);188return this;189}190}191192@Override193@SuppressWarnings("unchecked")194public <T> T getOption(SocketOption<T> name)195throws IOException196{197if (name == null)198throw new NullPointerException();199if (!supportedOptions().contains(name))200throw new UnsupportedOperationException("'" + name + "' not supported");201202synchronized (stateLock) {203if (!isOpen())204throw new ClosedChannelException();205206if (name == StandardSocketOptions.SO_REUSEADDR &&207Net.useExclusiveBind())208{209// SO_REUSEADDR emulated when using exclusive bind210return (T)Boolean.valueOf(isReuseAddress);211}212213// special handling for IP_TOS: always return 0 when IPv6214if (name == StandardSocketOptions.IP_TOS) {215ProtocolFamily family = Net.isIPv6Available() ?216StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;217return (T) Net.getSocketOption(fd, family, name);218}219220// no options that require special handling221return (T) Net.getSocketOption(fd, Net.UNSPEC, name);222}223}224225private static class DefaultOptionsHolder {226static final Set<SocketOption<?>> defaultOptions = defaultOptions();227228private static Set<SocketOption<?>> defaultOptions() {229HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);230set.add(StandardSocketOptions.SO_SNDBUF);231set.add(StandardSocketOptions.SO_RCVBUF);232set.add(StandardSocketOptions.SO_KEEPALIVE);233set.add(StandardSocketOptions.SO_REUSEADDR);234set.add(StandardSocketOptions.SO_LINGER);235set.add(StandardSocketOptions.TCP_NODELAY);236// additional options required by socket adaptor237set.add(StandardSocketOptions.IP_TOS);238set.add(ExtendedSocketOption.SO_OOBINLINE);239if (ExtendedOptionsImpl.flowSupported()) {240set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);241}242set.addAll(ExtendedOptionsHelper.keepAliveOptions());243return Collections.unmodifiableSet(set);244}245}246247@Override248public final Set<SocketOption<?>> supportedOptions() {249return DefaultOptionsHolder.defaultOptions;250}251252private boolean ensureReadOpen() throws ClosedChannelException {253synchronized (stateLock) {254if (!isOpen())255throw new ClosedChannelException();256if (!isConnected())257throw new NotYetConnectedException();258if (!isInputOpen)259return false;260else261return true;262}263}264265private void ensureWriteOpen() throws ClosedChannelException {266synchronized (stateLock) {267if (!isOpen())268throw new ClosedChannelException();269if (!isOutputOpen)270throw new ClosedChannelException();271if (!isConnected())272throw new NotYetConnectedException();273}274}275276private void readerCleanup() throws IOException {277synchronized (stateLock) {278readerThread = 0;279if (state == ST_KILLPENDING)280kill();281}282}283284private void writerCleanup() throws IOException {285synchronized (stateLock) {286writerThread = 0;287if (state == ST_KILLPENDING)288kill();289}290}291292public int read(ByteBuffer buf) throws IOException {293294if (buf == null)295throw new NullPointerException();296297synchronized (readLock) {298if (!ensureReadOpen())299return -1;300int n = 0;301try {302303// Set up the interruption machinery; see304// AbstractInterruptibleChannel for details305//306begin();307308synchronized (stateLock) {309if (!isOpen()) {310// Either the current thread is already interrupted, so311// begin() closed the channel, or another thread closed the312// channel since we checked it a few bytecodes ago. In313// either case the value returned here is irrelevant since314// the invocation of end() in the finally block will throw315// an appropriate exception.316//317return 0;318319}320321// Save this thread so that it can be signalled on those322// platforms that require it323//324readerThread = NativeThread.current();325}326327// Between the previous test of isOpen() and the return of the328// IOUtil.read invocation below, this channel might be closed329// or this thread might be interrupted. We rely upon the330// implicit synchronization point in the kernel read() call to331// make sure that the right thing happens. In either case the332// implCloseSelectableChannel method is ultimately invoked in333// some other thread, so there are three possibilities:334//335// - implCloseSelectableChannel() invokes nd.preClose()336// before this thread invokes read(), in which case the337// read returns immediately with either EOF or an error,338// the latter of which will cause an IOException to be339// thrown.340//341// - implCloseSelectableChannel() invokes nd.preClose() after342// this thread is blocked in read(). On some operating343// systems (e.g., Solaris and Windows) this causes the read344// to return immediately with either EOF or an error345// indication.346//347// - implCloseSelectableChannel() invokes nd.preClose() after348// this thread is blocked in read() but the operating349// system (e.g., Linux) doesn't support preemptive close,350// so implCloseSelectableChannel() proceeds to signal this351// thread, thereby causing the read to return immediately352// with IOStatus.INTERRUPTED.353//354// In all three cases the invocation of end() in the finally355// clause will notice that the channel has been closed and356// throw an appropriate exception (AsynchronousCloseException357// or ClosedByInterruptException) if necessary.358//359// *There is A fourth possibility. implCloseSelectableChannel()360// invokes nd.preClose(), signals reader/writer thred and quickly361// moves on to nd.close() in kill(), which does a real close.362// Then a third thread accepts a new connection, opens file or363// whatever that causes the released "fd" to be recycled. All364// above happens just between our last isOpen() check and the365// next kernel read reached, with the recycled "fd". The solution366// is to postpone the real kill() if there is a reader or/and367// writer thread(s) over there "waiting", leave the cleanup/kill368// to the reader or writer thread. (the preClose() still happens369// so the connection gets cut off as usual).370//371// For socket channels there is the additional wrinkle that372// asynchronous shutdown works much like asynchronous close,373// except that the channel is shutdown rather than completely374// closed. This is analogous to the first two cases above,375// except that the shutdown operation plays the role of376// nd.preClose().377for (;;) {378n = IOUtil.read(fd, buf, -1, nd);379if ((n == IOStatus.INTERRUPTED) && isOpen()) {380// The system call was interrupted but the channel381// is still open, so retry382continue;383}384return IOStatus.normalize(n);385}386387} finally {388readerCleanup(); // Clear reader thread389// The end method, which is defined in our superclass390// AbstractInterruptibleChannel, resets the interruption391// machinery. If its argument is true then it returns392// normally; otherwise it checks the interrupt and open state393// of this channel and throws an appropriate exception if394// necessary.395//396// So, if we actually managed to do any I/O in the above try397// block then we pass true to the end method. We also pass398// true if the channel was in non-blocking mode when the I/O399// operation was initiated but no data could be transferred;400// this prevents spurious exceptions from being thrown in the401// rare event that a channel is closed or a thread is402// interrupted at the exact moment that a non-blocking I/O403// request is made.404//405end(n > 0 || (n == IOStatus.UNAVAILABLE));406407// Extra case for socket channels: Asynchronous shutdown408//409synchronized (stateLock) {410if ((n <= 0) && (!isInputOpen))411return IOStatus.EOF;412}413414assert IOStatus.check(n);415416}417}418}419420public long read(ByteBuffer[] dsts, int offset, int length)421throws IOException422{423if ((offset < 0) || (length < 0) || (offset > dsts.length - length))424throw new IndexOutOfBoundsException();425synchronized (readLock) {426if (!ensureReadOpen())427return -1;428long n = 0;429try {430begin();431synchronized (stateLock) {432if (!isOpen())433return 0;434readerThread = NativeThread.current();435}436437for (;;) {438n = IOUtil.read(fd, dsts, offset, length, nd);439if ((n == IOStatus.INTERRUPTED) && isOpen())440continue;441return IOStatus.normalize(n);442}443} finally {444readerCleanup();445end(n > 0 || (n == IOStatus.UNAVAILABLE));446synchronized (stateLock) {447if ((n <= 0) && (!isInputOpen))448return IOStatus.EOF;449}450assert IOStatus.check(n);451}452}453}454455public int write(ByteBuffer buf) throws IOException {456if (buf == null)457throw new NullPointerException();458synchronized (writeLock) {459ensureWriteOpen();460int n = 0;461try {462begin();463synchronized (stateLock) {464if (!isOpen())465return 0;466writerThread = NativeThread.current();467}468for (;;) {469n = IOUtil.write(fd, buf, -1, nd);470if ((n == IOStatus.INTERRUPTED) && isOpen())471continue;472return IOStatus.normalize(n);473}474} finally {475writerCleanup();476end(n > 0 || (n == IOStatus.UNAVAILABLE));477synchronized (stateLock) {478if ((n <= 0) && (!isOutputOpen))479throw new AsynchronousCloseException();480}481assert IOStatus.check(n);482}483}484}485486public long write(ByteBuffer[] srcs, int offset, int length)487throws IOException488{489if ((offset < 0) || (length < 0) || (offset > srcs.length - length))490throw new IndexOutOfBoundsException();491synchronized (writeLock) {492ensureWriteOpen();493long n = 0;494try {495begin();496synchronized (stateLock) {497if (!isOpen())498return 0;499writerThread = NativeThread.current();500}501for (;;) {502n = IOUtil.write(fd, srcs, offset, length, nd);503if ((n == IOStatus.INTERRUPTED) && isOpen())504continue;505return IOStatus.normalize(n);506}507} finally {508writerCleanup();509end((n > 0) || (n == IOStatus.UNAVAILABLE));510synchronized (stateLock) {511if ((n <= 0) && (!isOutputOpen))512throw new AsynchronousCloseException();513}514assert IOStatus.check(n);515}516}517}518519// package-private520int sendOutOfBandData(byte b) throws IOException {521synchronized (writeLock) {522ensureWriteOpen();523int n = 0;524try {525begin();526synchronized (stateLock) {527if (!isOpen())528return 0;529writerThread = NativeThread.current();530}531for (;;) {532n = sendOutOfBandData(fd, b);533if ((n == IOStatus.INTERRUPTED) && isOpen())534continue;535return IOStatus.normalize(n);536}537} finally {538writerCleanup();539end((n > 0) || (n == IOStatus.UNAVAILABLE));540synchronized (stateLock) {541if ((n <= 0) && (!isOutputOpen))542throw new AsynchronousCloseException();543}544assert IOStatus.check(n);545}546}547}548549protected void implConfigureBlocking(boolean block) throws IOException {550IOUtil.configureBlocking(fd, block);551}552553public InetSocketAddress localAddress() {554synchronized (stateLock) {555return localAddress;556}557}558559public SocketAddress remoteAddress() {560synchronized (stateLock) {561return remoteAddress;562}563}564565@Override566public SocketChannel bind(SocketAddress local) throws IOException {567synchronized (readLock) {568synchronized (writeLock) {569synchronized (stateLock) {570if (!isOpen())571throw new ClosedChannelException();572if (state == ST_PENDING)573throw new ConnectionPendingException();574if (localAddress != null)575throw new AlreadyBoundException();576InetSocketAddress isa = (local == null) ?577new InetSocketAddress(0) : Net.checkAddress(local);578SecurityManager sm = System.getSecurityManager();579if (sm != null) {580sm.checkListen(isa.getPort());581}582NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());583Net.bind(fd, isa.getAddress(), isa.getPort());584localAddress = Net.localAddress(fd);585}586}587}588return this;589}590591public boolean isConnected() {592synchronized (stateLock) {593return (state == ST_CONNECTED);594}595}596597public boolean isConnectionPending() {598synchronized (stateLock) {599return (state == ST_PENDING);600}601}602603void ensureOpenAndUnconnected() throws IOException { // package-private604synchronized (stateLock) {605if (!isOpen())606throw new ClosedChannelException();607if (state == ST_CONNECTED)608throw new AlreadyConnectedException();609if (state == ST_PENDING)610throw new ConnectionPendingException();611}612}613614public boolean connect(SocketAddress sa) throws IOException {615int localPort = 0;616617synchronized (readLock) {618synchronized (writeLock) {619ensureOpenAndUnconnected();620InetSocketAddress isa = Net.checkAddress(sa);621SecurityManager sm = System.getSecurityManager();622if (sm != null)623sm.checkConnect(isa.getAddress().getHostAddress(),624isa.getPort());625synchronized (blockingLock()) {626int n = 0;627try {628try {629begin();630synchronized (stateLock) {631if (!isOpen()) {632return false;633}634// notify hook only if unbound635if (localAddress == null) {636NetHooks.beforeTcpConnect(fd,637isa.getAddress(),638isa.getPort());639}640readerThread = NativeThread.current();641}642for (;;) {643InetAddress ia = isa.getAddress();644if (ia.isAnyLocalAddress())645ia = InetAddress.getLocalHost();646n = Net.connect(fd,647ia,648isa.getPort());649if ( (n == IOStatus.INTERRUPTED)650&& isOpen())651continue;652break;653}654655} finally {656readerCleanup();657end((n > 0) || (n == IOStatus.UNAVAILABLE));658assert IOStatus.check(n);659}660} catch (IOException x) {661// If an exception was thrown, close the channel after662// invoking end() so as to avoid bogus663// AsynchronousCloseExceptions664close();665throw x;666}667synchronized (stateLock) {668remoteAddress = isa;669if (n > 0) {670671// Connection succeeded; disallow further672// invocation673state = ST_CONNECTED;674if (isOpen())675localAddress = Net.localAddress(fd);676return true;677}678// If nonblocking and no exception then connection679// pending; disallow another invocation680if (!isBlocking())681state = ST_PENDING;682else683assert false;684}685}686return false;687}688}689}690691public boolean finishConnect() throws IOException {692synchronized (readLock) {693synchronized (writeLock) {694synchronized (stateLock) {695if (!isOpen())696throw new ClosedChannelException();697if (state == ST_CONNECTED)698return true;699if (state != ST_PENDING)700throw new NoConnectionPendingException();701}702int n = 0;703try {704try {705begin();706synchronized (blockingLock()) {707synchronized (stateLock) {708if (!isOpen()) {709return false;710}711readerThread = NativeThread.current();712}713if (!isBlocking()) {714for (;;) {715n = checkConnect(fd, false,716readyToConnect);717if ( (n == IOStatus.INTERRUPTED)718&& isOpen())719continue;720break;721}722} else {723for (;;) {724n = checkConnect(fd, true,725readyToConnect);726if (n == 0) {727// Loop in case of728// spurious notifications729continue;730}731if ( (n == IOStatus.INTERRUPTED)732&& isOpen())733continue;734break;735}736}737}738} finally {739synchronized (stateLock) {740readerThread = 0;741if (state == ST_KILLPENDING) {742kill();743// poll()/getsockopt() does not report744// error (throws exception, with n = 0)745// on Linux platform after dup2 and746// signal-wakeup. Force n to 0 so the747// end() can throw appropriate exception748n = 0;749}750}751end((n > 0) || (n == IOStatus.UNAVAILABLE));752assert IOStatus.check(n);753}754} catch (IOException x) {755// If an exception was thrown, close the channel after756// invoking end() so as to avoid bogus757// AsynchronousCloseExceptions758close();759throw x;760}761if (n > 0) {762synchronized (stateLock) {763state = ST_CONNECTED;764if (isOpen())765localAddress = Net.localAddress(fd);766}767return true;768}769return false;770}771}772}773774@Override775public SocketChannel shutdownInput() throws IOException {776synchronized (stateLock) {777if (!isOpen())778throw new ClosedChannelException();779if (!isConnected())780throw new NotYetConnectedException();781if (isInputOpen) {782Net.shutdown(fd, Net.SHUT_RD);783if (readerThread != 0)784NativeThread.signal(readerThread);785isInputOpen = false;786}787return this;788}789}790791@Override792public SocketChannel shutdownOutput() throws IOException {793synchronized (stateLock) {794if (!isOpen())795throw new ClosedChannelException();796if (!isConnected())797throw new NotYetConnectedException();798if (isOutputOpen) {799Net.shutdown(fd, Net.SHUT_WR);800if (writerThread != 0)801NativeThread.signal(writerThread);802isOutputOpen = false;803}804return this;805}806}807808public boolean isInputOpen() {809synchronized (stateLock) {810return isInputOpen;811}812}813814public boolean isOutputOpen() {815synchronized (stateLock) {816return isOutputOpen;817}818}819820// AbstractInterruptibleChannel synchronizes invocations of this method821// using AbstractInterruptibleChannel.closeLock, and also ensures that this822// method is only ever invoked once. Before we get to this method, isOpen823// (which is volatile) will have been set to false.824//825protected void implCloseSelectableChannel() throws IOException {826synchronized (stateLock) {827isInputOpen = false;828isOutputOpen = false;829830// Close the underlying file descriptor and dup it to a known fd831// that's already closed. This prevents other operations on this832// channel from using the old fd, which might be recycled in the833// meantime and allocated to an entirely different channel.834//835if (state != ST_KILLED)836nd.preClose(fd);837838// Signal native threads, if needed. If a target thread is not839// currently blocked in an I/O operation then no harm is done since840// the signal handler doesn't actually do anything.841//842if (readerThread != 0)843NativeThread.signal(readerThread);844845if (writerThread != 0)846NativeThread.signal(writerThread);847848// If this channel is not registered then it's safe to close the fd849// immediately since we know at this point that no thread is850// blocked in an I/O operation upon the channel and, since the851// channel is marked closed, no thread will start another such852// operation. If this channel is registered then we don't close853// the fd since it might be in use by a selector. In that case854// closing this channel caused its keys to be cancelled, so the855// last selector to deregister a key for this channel will invoke856// kill() to close the fd.857//858if (!isRegistered())859kill();860}861}862863public void kill() throws IOException {864synchronized (stateLock) {865if (state == ST_KILLED)866return;867if (state == ST_UNINITIALIZED) {868state = ST_KILLED;869return;870}871assert !isOpen() && !isRegistered();872873// Postpone the kill if there is a waiting reader874// or writer thread. See the comments in read() for875// more detailed explanation.876if (readerThread == 0 && writerThread == 0) {877nd.close(fd);878state = ST_KILLED;879} else {880state = ST_KILLPENDING;881}882}883}884885/**886* Translates native poll revent ops into a ready operation ops887*/888public boolean translateReadyOps(int ops, int initialOps,889SelectionKeyImpl sk) {890int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes891int oldOps = sk.nioReadyOps();892int newOps = initialOps;893894if ((ops & Net.POLLNVAL) != 0) {895// This should only happen if this channel is pre-closed while a896// selection operation is in progress897// ## Throw an error if this channel has not been pre-closed898return false;899}900901if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {902newOps = intOps;903sk.nioReadyOps(newOps);904// No need to poll again in checkConnect,905// the error will be detected there906readyToConnect = true;907return (newOps & ~oldOps) != 0;908}909910if (((ops & Net.POLLIN) != 0) &&911((intOps & SelectionKey.OP_READ) != 0) &&912(state == ST_CONNECTED))913newOps |= SelectionKey.OP_READ;914915if (((ops & Net.POLLCONN) != 0) &&916((intOps & SelectionKey.OP_CONNECT) != 0) &&917((state == ST_UNCONNECTED) || (state == ST_PENDING))) {918newOps |= SelectionKey.OP_CONNECT;919readyToConnect = true;920}921922if (((ops & Net.POLLOUT) != 0) &&923((intOps & SelectionKey.OP_WRITE) != 0) &&924(state == ST_CONNECTED))925newOps |= SelectionKey.OP_WRITE;926927sk.nioReadyOps(newOps);928return (newOps & ~oldOps) != 0;929}930931public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {932return translateReadyOps(ops, sk.nioReadyOps(), sk);933}934935public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {936return translateReadyOps(ops, 0, sk);937}938939// package-private940int poll(int events, long timeout) throws IOException {941assert Thread.holdsLock(blockingLock()) && !isBlocking();942943synchronized (readLock) {944int n = 0;945try {946begin();947synchronized (stateLock) {948if (!isOpen())949return 0;950readerThread = NativeThread.current();951}952n = Net.poll(fd, events, timeout);953} finally {954readerCleanup();955end(n > 0);956}957return n;958}959}960961/**962* Translates an interest operation set into a native poll event set963*/964public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {965int newOps = 0;966if ((ops & SelectionKey.OP_READ) != 0)967newOps |= Net.POLLIN;968if ((ops & SelectionKey.OP_WRITE) != 0)969newOps |= Net.POLLOUT;970if ((ops & SelectionKey.OP_CONNECT) != 0)971newOps |= Net.POLLCONN;972sk.selector.putEventOps(sk, newOps);973}974975public FileDescriptor getFD() {976return fd;977}978979public int getFDVal() {980return fdVal;981}982983@Override984public String toString() {985StringBuffer sb = new StringBuffer();986sb.append(this.getClass().getSuperclass().getName());987sb.append('[');988if (!isOpen())989sb.append("closed");990else {991synchronized (stateLock) {992switch (state) {993case ST_UNCONNECTED:994sb.append("unconnected");995break;996case ST_PENDING:997sb.append("connection-pending");998break;999case ST_CONNECTED:1000sb.append("connected");1001if (!isInputOpen)1002sb.append(" ishut");1003if (!isOutputOpen)1004sb.append(" oshut");1005break;1006}1007InetSocketAddress addr = localAddress();1008if (addr != null) {1009sb.append(" local=");1010sb.append(Net.getRevealedLocalAddressAsString(addr));1011}1012if (remoteAddress() != null) {1013sb.append(" remote=");1014sb.append(remoteAddress().toString());1015}1016}1017}1018sb.append(']');1019return sb.toString();1020}102110221023// -- Native methods --10241025private static native int checkConnect(FileDescriptor fd,1026boolean block, boolean ready)1027throws IOException;10281029private static native int sendOutOfBandData(FileDescriptor fd, byte data)1030throws IOException;10311032static {1033IOUtil.load();1034nd = new SocketDispatcher();1035}10361037}103810391040