997 lines · 36.6 KB · Java
RawDownload
    int sendOutOfBandData(byte b) throws IOException {        synchronized (writeLock) {            ensureWriteOpen();            int n = 0;            try {                begin();                synchronized (stateLock) {                    if (!isOpen())                        return 0;                    writerThread = NativeThread.current();                }                for (;;) {                    n = sendOutOfBandData(fd, b);                    if ((n == IOStatus.INTERRUPTED) && isOpen())                        continue;                    return IOStatus.normalize(n);                }            } finally {                writerCleanup();                end((n > 0) || (n == IOStatus.UNAVAILABLE));                synchronized (stateLock) {                    if ((n <= 0) && (!isOutputOpen))                        throw new AsynchronousCloseException();                }                assert IOStatus.check(n);            }        }    }     protected void implConfigureBlocking(boolean block) throws IOException {        IOUtil.configureBlocking(fd, block);    }     public SocketAddress localAddress() {        synchronized (stateLock) {            return localAddress;        }    }     public SocketAddress remoteAddress() {        synchronized (stateLock) {            return remoteAddress;        }    }     @Override    public SocketChannel bind(SocketAddress local) throws IOException {        synchronized (readLock) {            synchronized (writeLock) {                synchronized (stateLock) {                    if (!isOpen())                        throw new ClosedChannelException();                    if (state == ST_PENDING)                        throw new ConnectionPendingException();                    if (localAddress != null)                        throw new AlreadyBoundException();                    InetSocketAddress isa = (local == null) ?                        new InetSocketAddress(0) : Net.checkAddress(local);                    NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());                    Net.bind(fd, isa.getAddress(), isa.getPort());                    localAddress = Net.localAddress(fd);                }            }        }        return this;    }     public boolean isConnected() {        synchronized (stateLock) {            return (state == ST_CONNECTED);        }    }     public boolean isConnectionPending() {        synchronized (stateLock) {            return (state == ST_PENDING);        }    }     void ensureOpenAndUnconnected() throws IOException { // package-private        synchronized (stateLock) {            if (!isOpen())                throw new ClosedChannelException();            if (state == ST_CONNECTED)                throw new AlreadyConnectedException();            if (state == ST_PENDING)                throw new ConnectionPendingException();        }    }     public boolean connect(SocketAddress sa) throws IOException {        int localPort = 0;         synchronized (readLock) {            synchronized (writeLock) {                ensureOpenAndUnconnected();                InetSocketAddress isa = Net.checkAddress(sa);                SecurityManager sm = System.getSecurityManager();                if (sm != null)                    sm.checkConnect(isa.getAddress().getHostAddress(),                                    isa.getPort());                synchronized (blockingLock()) {                    int n = 0;                    try {                        try {                            begin();                            synchronized (stateLock) {                                if (!isOpen()) {                                    return false;                                }                                // notify hook only if unbound                                if (localAddress == null) {                                    NetHooks.beforeTcpConnect(fd,                                                           isa.getAddress(),                                                           isa.getPort());                                }                                readerThread = NativeThread.current();                            }                            for (;;) {                                InetAddress ia = isa.getAddress();                                if (ia.isAnyLocalAddress())                                    ia = InetAddress.getLocalHost();                                n = Net.connect(fd,                                                ia,                                                isa.getPort());                                if (  (n == IOStatus.INTERRUPTED)                                      && isOpen())                                    continue;                                break;                            }                             synchronized (stateLock) {                                if (isOpen() && (localAddress == null) ||                                    ((InetSocketAddress)localAddress)                                        .getAddress().isAnyLocalAddress())                                {                                    // Socket was not bound before connecting or                                    // Socket was bound with an "anyLocalAddress"                                    localAddress = Net.localAddress(fd);                                }                            }                         } finally {                            readerCleanup();                            end((n > 0) || (n == IOStatus.UNAVAILABLE));                            assert IOStatus.check(n);                        }                    } catch (IOException x) {                        // If an exception was thrown, close the channel after                        // invoking end() so as to avoid bogus                        // AsynchronousCloseExceptions                        close();                        throw x;                    }                    synchronized (stateLock) {                        remoteAddress = isa;                        if (n > 0) {                             // Connection succeeded; disallow further                            // invocation                            state = ST_CONNECTED;                            return true;                        }                        // If nonblocking and no exception then connection                        // pending; disallow another invocation                        if (!isBlocking())                            state = ST_PENDING;                        else                            assert false;                    }                }                return false;            }        }    }     public boolean finishConnect() throws IOException {        synchronized (readLock) {            synchronized (writeLock) {                synchronized (stateLock) {                    if (!isOpen())                        throw new ClosedChannelException();                    if (state == ST_CONNECTED)                        return true;                    if (state != ST_PENDING)                        throw new NoConnectionPendingException();                }                int n = 0;                try {                    try {                        begin();                        synchronized (blockingLock()) {                            synchronized (stateLock) {                                if (!isOpen()) {                                    return false;                                }                                readerThread = NativeThread.current();                            }                            if (!isBlocking()) {                                for (;;) {                                    n = checkConnect(fd, false,                                                     readyToConnect);                                    if (  (n == IOStatus.INTERRUPTED)                                          && isOpen())                                        continue;                                    break;                                }                            } else {                                for (;;) {                                    n = checkConnect(fd, true,                                                     readyToConnect);                                    if (n == 0) {                                        // Loop in case of                                        // spurious notifications                                        continue;                                    }                                    if (  (n == IOStatus.INTERRUPTED)                                          && isOpen())                                        continue;                                    break;                                }                            }                        }                    } finally {                        synchronized (stateLock) {                            readerThread = 0;                            if (state == ST_KILLPENDING) {                                kill();                                // poll()/getsockopt() does not report                                // error (throws exception, with n = 0)                                // on Linux platform after dup2 and                                // signal-wakeup. Force n to 0 so the                                // end() can throw appropriate exception                                n = 0;                            }                        }                        end((n > 0) || (n == IOStatus.UNAVAILABLE));                        assert IOStatus.check(n);                    }                } catch (IOException x) {                    // If an exception was thrown, close the channel after                    // invoking end() so as to avoid bogus                    // AsynchronousCloseExceptions                    close();                    throw x;                }                if (n > 0) {                    synchronized (stateLock) {                        state = ST_CONNECTED;                    }                    return true;                }                return false;            }        }    }     @Override    public SocketChannel shutdownInput() throws IOException {        synchronized (stateLock) {            if (!isOpen())                throw new ClosedChannelException();            if (!isConnected())                throw new NotYetConnectedException();            if (isInputOpen) {                Net.shutdown(fd, Net.SHUT_RD);                if (readerThread != 0)                    NativeThread.signal(readerThread);                isInputOpen = false;            }            return this;        }    }     @Override    public SocketChannel shutdownOutput() throws IOException {        synchronized (stateLock) {            if (!isOpen())                throw new ClosedChannelException();            if (!isConnected())                throw new NotYetConnectedException();            if (isOutputOpen) {                Net.shutdown(fd, Net.SHUT_WR);                if (writerThread != 0)                    NativeThread.signal(writerThread);                isOutputOpen = false;            }            return this;        }    }     public boolean isInputOpen() {        synchronized (stateLock) {            return isInputOpen;        }    }     public boolean isOutputOpen() {        synchronized (stateLock) {            return isOutputOpen;        }    }     // AbstractInterruptibleChannel synchronizes invocations of this method    // using AbstractInterruptibleChannel.closeLock, and also ensures that this    // method is only ever invoked once.  Before we get to this method, isOpen    // (which is volatile) will have been set to false.    //    protected void implCloseSelectableChannel() throws IOException {        synchronized (stateLock) {            isInputOpen = false;            isOutputOpen = false;             // Close the underlying file descriptor and dup it to a known fd            // that's already closed.  This prevents other operations on this            // channel from using the old fd, which might be recycled in the            // meantime and allocated to an entirely different channel.            //            nd.preClose(fd);             // Signal native threads, if needed.  If a target thread is not            // currently blocked in an I/O operation then no harm is done since            // the signal handler doesn't actually do anything.            //            if (readerThread != 0)                NativeThread.signal(readerThread);             if (writerThread != 0)                NativeThread.signal(writerThread);             // If this channel is not registered then it's safe to close the fd            // immediately since we know at this point that no thread is            // blocked in an I/O operation upon the channel and, since the            // channel is marked closed, no thread will start another such            // operation.  If this channel is registered then we don't close            // the fd since it might be in use by a selector.  In that case            // closing this channel caused its keys to be cancelled, so the            // last selector to deregister a key for this channel will invoke            // kill() to close the fd.            //            if (!isRegistered())                kill();        }    }     public void kill() throws IOException {        synchronized (stateLock) {            if (state == ST_KILLED)                return;            if (state == ST_UNINITIALIZED) {                state = ST_KILLED;                return;            }            assert !isOpen() && !isRegistered();             // Postpone the kill if there is a waiting reader            // or writer thread. See the comments in read() for            // more detailed explanation.            if (readerThread == 0 && writerThread == 0) {                nd.close(fd);                state = ST_KILLED;            } else {                state = ST_KILLPENDING;            }        }    }     /**     * Translates native poll revent ops into a ready operation ops     */    public boolean translateReadyOps(int ops, int initialOps,                                     SelectionKeyImpl sk) {        int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes        int oldOps = sk.nioReadyOps();        int newOps = initialOps;         if ((ops & PollArrayWrapper.POLLNVAL) != 0) {            // This should only happen if this channel is pre-closed while a            // selection operation is in progress            // ## Throw an error if this channel has not been pre-closed            return false;        }         if ((ops & (PollArrayWrapper.POLLERR                    | PollArrayWrapper.POLLHUP)) != 0) {            newOps = intOps;            sk.nioReadyOps(newOps);            // No need to poll again in checkConnect,            // the error will be detected there            readyToConnect = true;            return (newOps & ~oldOps) != 0;        }         if (((ops & PollArrayWrapper.POLLIN) != 0) &&            ((intOps & SelectionKey.OP_READ) != 0) &&            (state == ST_CONNECTED))            newOps |= SelectionKey.OP_READ;         if (((ops & PollArrayWrapper.POLLCONN) != 0) &&            ((intOps & SelectionKey.OP_CONNECT) != 0) &&            ((state == ST_UNCONNECTED) || (state == ST_PENDING))) {            newOps |= SelectionKey.OP_CONNECT;            readyToConnect = true;        }         if (((ops & PollArrayWrapper.POLLOUT) != 0) &&            ((intOps & SelectionKey.OP_WRITE) != 0) &&            (state == ST_CONNECTED))            newOps |= SelectionKey.OP_WRITE;         sk.nioReadyOps(newOps);        return (newOps & ~oldOps) != 0;    }     public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {        return translateReadyOps(ops, sk.nioReadyOps(), sk);    }     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {        return translateReadyOps(ops, 0, sk);    }     /**     * Translates an interest operation set into a native poll event set     */    public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {        int newOps = 0;        if ((ops & SelectionKey.OP_READ) != 0)            newOps |= PollArrayWrapper.POLLIN;        if ((ops & SelectionKey.OP_WRITE) != 0)            newOps |= PollArrayWrapper.POLLOUT;        if ((ops & SelectionKey.OP_CONNECT) != 0)            newOps |= PollArrayWrapper.POLLCONN;        sk.selector.putEventOps(sk, newOps);    }     public FileDescriptor getFD() {        return fd;    }     public int getFDVal() {        return fdVal;    }     public String toString() {        StringBuffer sb = new StringBuffer();        sb.append(this.getClass().getSuperclass().getName());        sb.append('[');        if (!isOpen())            sb.append("closed");        else {            synchronized (stateLock) {                switch (state) {                case ST_UNCONNECTED:                    sb.append("unconnected");                    break;                case ST_PENDING:                    sb.append("connection-pending");                    break;                case ST_CONNECTED:                    sb.append("connected");                    if (!isInputOpen)                        sb.append(" ishut");                    if (!isOutputOpen)                        sb.append(" oshut");                    break;                }                if (localAddress() != null) {                    sb.append(" local=");                    sb.append(localAddress().toString());                }                if (remoteAddress() != null) {                    sb.append(" remote=");                    sb.append(remoteAddress().toString());                }            }        }        sb.append(']');        return sb.toString();    }      // -- Native methods --     private static native int checkConnect(FileDescriptor fd,                                           boolean block, boolean ready)        throws IOException;     private static native int sendOutOfBandData(FileDescriptor fd, byte data)        throws IOException;     static {        Util.load();        nd = new SocketDispatcher();    } }

Lines 501–997 of 997. Previous lines