Search in sources :

Example 31 with SelectionKey

use of java.nio.channels.SelectionKey in project tomcat by apache.

the class NioBlockingSelector method write.

/**
     * Performs a blocking write using the bytebuffer for data to be written
     * If the <code>selector</code> parameter is null, then it will perform a busy write that could
     * take up a lot of CPU cycles.
     * @param buf ByteBuffer - the buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
     * @param socket SocketChannel - the socket to write data to
     * @param writeTimeout long - the timeout for this write operation in milliseconds, -1 means no timeout
     * @return int - returns the number of bytes written
     * @throws EOFException if write returns -1
     * @throws SocketTimeoutException if the write times out
     * @throws IOException if an IO Exception occurs in the underlying socket logic
     */
public int write(ByteBuffer buf, NioChannel socket, long writeTimeout) throws IOException {
    SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
    if (key == null)
        throw new IOException("Key no longer registered");
    KeyReference reference = keyReferenceStack.pop();
    if (reference == null) {
        reference = new KeyReference();
    }
    NioSocketWrapper att = (NioSocketWrapper) key.attachment();
    int written = 0;
    boolean timedout = false;
    //assume we can write
    int keycount = 1;
    //start the timeout timer
    long time = System.currentTimeMillis();
    try {
        while ((!timedout) && buf.hasRemaining()) {
            if (keycount > 0) {
                //only write if we were registered for a write
                //write the data
                int cnt = socket.write(buf);
                if (cnt == -1)
                    throw new EOFException();
                written += cnt;
                if (cnt > 0) {
                    //reset our timeout timer
                    time = System.currentTimeMillis();
                    //we successfully wrote, try again without a selector
                    continue;
                }
            }
            try {
                if (att.getWriteLatch() == null || att.getWriteLatch().getCount() == 0)
                    att.startWriteLatch(1);
                poller.add(att, SelectionKey.OP_WRITE, reference);
                if (writeTimeout < 0) {
                    att.awaitWriteLatch(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
                } else {
                    att.awaitWriteLatch(writeTimeout, TimeUnit.MILLISECONDS);
                }
            } catch (InterruptedException ignore) {
            // Ignore
            }
            if (att.getWriteLatch() != null && att.getWriteLatch().getCount() > 0) {
                //we got interrupted, but we haven't received notification from the poller.
                keycount = 0;
            } else {
                //latch countdown has happened
                keycount = 1;
                att.resetWriteLatch();
            }
            if (writeTimeout > 0 && (keycount == 0))
                timedout = (System.currentTimeMillis() - time) >= writeTimeout;
        }
        //while
        if (timedout)
            throw new SocketTimeoutException();
    } finally {
        poller.remove(att, SelectionKey.OP_WRITE);
        if (timedout && reference.key != null) {
            poller.cancelKey(reference.key);
        }
        reference.key = null;
        keyReferenceStack.push(reference);
    }
    return written;
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketTimeoutException(java.net.SocketTimeoutException) NioSocketWrapper(org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper) EOFException(java.io.EOFException) IOException(java.io.IOException)

Example 32 with SelectionKey

use of java.nio.channels.SelectionKey in project tomcat by apache.

the class NioBlockingSelector method read.

/**
     * Performs a blocking read using the bytebuffer for data to be read
     * If the <code>selector</code> parameter is null, then it will perform a busy read that could
     * take up a lot of CPU cycles.
     * @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
     * @param socket SocketChannel - the socket to write data to
     * @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
     * @return int - returns the number of bytes read
     * @throws EOFException if read returns -1
     * @throws SocketTimeoutException if the read times out
     * @throws IOException if an IO Exception occurs in the underlying socket logic
     */
public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException {
    SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
    if (key == null)
        throw new IOException("Key no longer registered");
    KeyReference reference = keyReferenceStack.pop();
    if (reference == null) {
        reference = new KeyReference();
    }
    NioSocketWrapper att = (NioSocketWrapper) key.attachment();
    int read = 0;
    boolean timedout = false;
    //assume we can read
    int keycount = 1;
    //start the timeout timer
    long time = System.currentTimeMillis();
    try {
        while (!timedout) {
            if (keycount > 0) {
                //only read if we were registered for a read
                read = socket.read(buf);
                if (read != 0) {
                    break;
                }
            }
            try {
                if (att.getReadLatch() == null || att.getReadLatch().getCount() == 0)
                    att.startReadLatch(1);
                poller.add(att, SelectionKey.OP_READ, reference);
                if (readTimeout < 0) {
                    att.awaitReadLatch(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
                } else {
                    att.awaitReadLatch(readTimeout, TimeUnit.MILLISECONDS);
                }
            } catch (InterruptedException ignore) {
            // Ignore
            }
            if (att.getReadLatch() != null && att.getReadLatch().getCount() > 0) {
                //we got interrupted, but we haven't received notification from the poller.
                keycount = 0;
            } else {
                //latch countdown has happened
                keycount = 1;
                att.resetReadLatch();
            }
            if (readTimeout >= 0 && (keycount == 0))
                timedout = (System.currentTimeMillis() - time) >= readTimeout;
        }
        //while
        if (timedout)
            throw new SocketTimeoutException();
    } finally {
        poller.remove(att, SelectionKey.OP_READ);
        if (timedout && reference.key != null) {
            poller.cancelKey(reference.key);
        }
        reference.key = null;
        keyReferenceStack.push(reference);
    }
    return read;
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketTimeoutException(java.net.SocketTimeoutException) NioSocketWrapper(org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper) IOException(java.io.IOException)

Example 33 with SelectionKey

use of java.nio.channels.SelectionKey in project tomcat by apache.

the class NioSelectorPool method read.

/**
     * Performs a read using the bytebuffer for data to be read and a selector to register for events should
     * you have the block=true.
     * If the <code>selector</code> parameter is null, then it will perform a busy read that could
     * take up a lot of CPU cycles.
     * @param buf ByteBuffer - the buffer containing the data, we will read as until we have read at least one byte or we timed out
     * @param socket SocketChannel - the socket to write data to
     * @param selector Selector - the selector to use for blocking, if null then a busy read will be initiated
     * @param readTimeout long - the timeout for this read operation in milliseconds, -1 means no timeout
     * @param block - true if you want to block until data becomes available or timeout time has been reached
     * @return int - returns the number of bytes read
     * @throws EOFException if read returns -1
     * @throws SocketTimeoutException if the read times out
     * @throws IOException if an IO Exception occurs in the underlying socket logic
     */
public int read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout, boolean block) throws IOException {
    if (SHARED && block) {
        return blockingSelector.read(buf, socket, readTimeout);
    }
    SelectionKey key = null;
    int read = 0;
    boolean timedout = false;
    //assume we can write
    int keycount = 1;
    //start the timeout timer
    long time = System.currentTimeMillis();
    try {
        while ((!timedout)) {
            int cnt = 0;
            if (keycount > 0) {
                //only read if we were registered for a read
                cnt = socket.read(buf);
                if (cnt == -1) {
                    if (read == 0) {
                        read = -1;
                    }
                    break;
                }
                read += cnt;
                //read some more
                if (cnt > 0)
                    continue;
                //we are done reading
                if (cnt == 0 && (read > 0 || (!block)))
                    break;
            }
            if (selector != null) {
                //register OP_WRITE to the selector
                if (key == null)
                    key = socket.getIOChannel().register(selector, SelectionKey.OP_READ);
                else
                    key.interestOps(SelectionKey.OP_READ);
                if (readTimeout == 0) {
                    timedout = (read == 0);
                } else if (readTimeout < 0) {
                    keycount = selector.select();
                } else {
                    keycount = selector.select(readTimeout);
                }
            }
            if (readTimeout > 0 && (selector == null || keycount == 0))
                timedout = (System.currentTimeMillis() - time) >= readTimeout;
        }
        //while
        if (timedout)
            throw new SocketTimeoutException();
    } finally {
        if (key != null) {
            key.cancel();
            //removes the key from this selector
            if (selector != null)
                selector.selectNow();
        }
    }
    return read;
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketTimeoutException(java.net.SocketTimeoutException)

Example 34 with SelectionKey

use of java.nio.channels.SelectionKey in project tomcat by apache.

the class NioSelectorPool method write.

/**
     * Performs a write using the bytebuffer for data to be written and a
     * selector to block (if blocking is requested). If the
     * <code>selector</code> parameter is null, and blocking is requested then
     * it will perform a busy write that could take up a lot of CPU cycles.
     * @param buf           The buffer containing the data, we will write as long as <code>(buf.hasRemaining()==true)</code>
     * @param socket        The socket to write data to
     * @param selector      The selector to use for blocking, if null then a busy write will be initiated
     * @param writeTimeout  The timeout for this write operation in milliseconds, -1 means no timeout
     * @param block         <code>true</code> to perform a blocking write
     *                      otherwise a non-blocking write will be performed
     * @return int - returns the number of bytes written
     * @throws EOFException if write returns -1
     * @throws SocketTimeoutException if the write times out
     * @throws IOException if an IO Exception occurs in the underlying socket logic
     */
public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout, boolean block) throws IOException {
    if (SHARED && block) {
        return blockingSelector.write(buf, socket, writeTimeout);
    }
    SelectionKey key = null;
    int written = 0;
    boolean timedout = false;
    //assume we can write
    int keycount = 1;
    //start the timeout timer
    long time = System.currentTimeMillis();
    try {
        while ((!timedout) && buf.hasRemaining()) {
            int cnt = 0;
            if (keycount > 0) {
                //only write if we were registered for a write
                //write the data
                cnt = socket.write(buf);
                if (cnt == -1)
                    throw new EOFException();
                written += cnt;
                if (cnt > 0) {
                    //reset our timeout timer
                    time = System.currentTimeMillis();
                    //we successfully wrote, try again without a selector
                    continue;
                }
                //don't block
                if (cnt == 0 && (!block))
                    break;
            }
            if (selector != null) {
                //register OP_WRITE to the selector
                if (key == null)
                    key = socket.getIOChannel().register(selector, SelectionKey.OP_WRITE);
                else
                    key.interestOps(SelectionKey.OP_WRITE);
                if (writeTimeout == 0) {
                    timedout = buf.hasRemaining();
                } else if (writeTimeout < 0) {
                    keycount = selector.select();
                } else {
                    keycount = selector.select(writeTimeout);
                }
            }
            if (writeTimeout > 0 && (selector == null || keycount == 0))
                timedout = (System.currentTimeMillis() - time) >= writeTimeout;
        }
        //while
        if (timedout)
            throw new SocketTimeoutException();
    } finally {
        if (key != null) {
            key.cancel();
            //removes the key from this selector
            if (selector != null)
                selector.selectNow();
        }
    }
    return written;
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketTimeoutException(java.net.SocketTimeoutException) EOFException(java.io.EOFException)

Example 35 with SelectionKey

use of java.nio.channels.SelectionKey in project tomcat by apache.

the class SecureNioChannel method rehandshake.

/**
     * Force a blocking handshake to take place for this key.
     * This requires that both network and application buffers have been emptied out prior to this call taking place, or a
     * IOException will be thrown.
     * @param timeout - timeout in milliseconds for each socket operation
     * @throws IOException - if an IO exception occurs or if application or network buffers contain data
     * @throws SocketTimeoutException - if a socket operation timed out
     */
// key cannot be null
@SuppressWarnings("null")
public void rehandshake(long timeout) throws IOException {
    //validate the network buffers are empty
    if (netInBuffer.position() > 0 && netInBuffer.position() < netInBuffer.limit())
        throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
    if (netOutBuffer.position() > 0 && netOutBuffer.position() < netOutBuffer.limit())
        throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
    if (!getBufHandler().isReadBufferEmpty())
        throw new IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
    if (!getBufHandler().isWriteBufferEmpty())
        throw new IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
    handshakeComplete = false;
    boolean isReadable = false;
    boolean isWriteable = false;
    boolean handshaking = true;
    Selector selector = null;
    SelectionKey key = null;
    try {
        sslEngine.beginHandshake();
        handshakeStatus = sslEngine.getHandshakeStatus();
        while (handshaking) {
            int hsStatus = this.handshake(isReadable, isWriteable);
            switch(hsStatus) {
                case -1:
                    throw new EOFException(sm.getString("channel.nio.ssl.eofDuringHandshake"));
                case 0:
                    handshaking = false;
                    break;
                default:
                    {
                        long now = System.currentTimeMillis();
                        if (selector == null) {
                            selector = Selector.open();
                            key = getIOChannel().register(selector, hsStatus);
                        } else {
                            // null warning supressed
                            key.interestOps(hsStatus);
                        }
                        int keyCount = selector.select(timeout);
                        if (keyCount == 0 && ((System.currentTimeMillis() - now) >= timeout)) {
                            throw new SocketTimeoutException(sm.getString("channel.nio.ssl.timeoutDuringHandshake"));
                        }
                        isReadable = key.isReadable();
                        isWriteable = key.isWritable();
                    }
            }
        }
    } catch (IOException x) {
        throw x;
    } catch (Exception cx) {
        IOException x = new IOException(cx);
        throw x;
    } finally {
        if (key != null)
            try {
                key.cancel();
            } catch (Exception ignore) {
            }
        if (selector != null)
            try {
                selector.close();
            } catch (Exception ignore) {
            }
    }
}
Also used : SelectionKey(java.nio.channels.SelectionKey) SocketTimeoutException(java.net.SocketTimeoutException) EOFException(java.io.EOFException) IOException(java.io.IOException) IOException(java.io.IOException) EOFException(java.io.EOFException) SSLException(javax.net.ssl.SSLException) SocketTimeoutException(java.net.SocketTimeoutException) Selector(java.nio.channels.Selector)

Aggregations

SelectionKey (java.nio.channels.SelectionKey)202 IOException (java.io.IOException)93 SocketChannel (java.nio.channels.SocketChannel)59 Selector (java.nio.channels.Selector)44 ServerSocketChannel (java.nio.channels.ServerSocketChannel)41 ClosedChannelException (java.nio.channels.ClosedChannelException)30 InetSocketAddress (java.net.InetSocketAddress)27 CancelledKeyException (java.nio.channels.CancelledKeyException)25 ByteBuffer (java.nio.ByteBuffer)24 ClosedSelectorException (java.nio.channels.ClosedSelectorException)17 SelectableChannel (java.nio.channels.SelectableChannel)13 Test (org.junit.Test)13 Iterator (java.util.Iterator)9 Socket (java.net.Socket)7 ArrayList (java.util.ArrayList)7 SocketTimeoutException (java.net.SocketTimeoutException)6 AbstractSelectionKey (java.nio.channels.spi.AbstractSelectionKey)6 EOFException (java.io.EOFException)5 DatagramChannel (java.nio.channels.DatagramChannel)5 HashSet (java.util.HashSet)5