103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.io.nio;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.InterruptedIOException;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.ClosedChannelException;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.SelectableChannel;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.SelectionKey;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.SocketChannel;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Locale;
2803928aee4356845252ac6b662d5c72c29903813eJake Slack
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.AsyncEndPoint;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.ConnectedEndPoint;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Connection;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.thread.Timeout.Task;
3803928aee4356845252ac6b662d5c72c29903813eJake Slack
3903928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
4003928aee4356845252ac6b662d5c72c29903813eJake Slack/**
4103928aee4356845252ac6b662d5c72c29903813eJake Slack * An Endpoint that can be scheduled by {@link SelectorManager}.
4203928aee4356845252ac6b662d5c72c29903813eJake Slack */
4303928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPoint, ConnectedEndPoint
4403928aee4356845252ac6b662d5c72c29903813eJake Slack{
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
4603928aee4356845252ac6b662d5c72c29903813eJake Slack
4703928aee4356845252ac6b662d5c72c29903813eJake Slack    private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final SelectorManager.SelectSet _selectSet;
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    private final SelectorManager _manager;
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    private  SelectionKey _key;
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Runnable _handler = new Runnable()
5203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
5303928aee4356845252ac6b662d5c72c29903813eJake Slack            public void run() { handle(); }
5403928aee4356845252ac6b662d5c72c29903813eJake Slack        };
5503928aee4356845252ac6b662d5c72c29903813eJake Slack
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** The desired value for {@link SelectionKey#interestOps()} */
5703928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _interestOps;
5803928aee4356845252ac6b662d5c72c29903813eJake Slack
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
6003928aee4356845252ac6b662d5c72c29903813eJake Slack     * The connection instance is the handler for any IO activity on the endpoint.
6103928aee4356845252ac6b662d5c72c29903813eJake Slack     * There is a different type of connection for HTTP, AJP, WebSocket and
6203928aee4356845252ac6b662d5c72c29903813eJake Slack     * ProxyConnect.   The connection may change for an SCEP as it is upgraded
6303928aee4356845252ac6b662d5c72c29903813eJake Slack     * from HTTP to proxy connect or websocket.
6403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile AsyncConnection _connection;
6603928aee4356845252ac6b662d5c72c29903813eJake Slack
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int STATE_NEEDS_DISPATCH=-1;
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int STATE_UNDISPATCHED=0;
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int STATE_DISPATCHED=1;
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int STATE_ASYNC=2;
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _state;
7203928aee4356845252ac6b662d5c72c29903813eJake Slack
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _onIdle;
7403928aee4356845252ac6b662d5c72c29903813eJake Slack
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** true if the last write operation succeed and wrote all offered bytes */
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile boolean _writable = true;
7703928aee4356845252ac6b662d5c72c29903813eJake Slack
7803928aee4356845252ac6b662d5c72c29903813eJake Slack
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    /** True if a thread has is blocked in {@link #blockReadable(long)} */
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _readBlocked;
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** True if a thread has is blocked in {@link #blockWritable(long)} */
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _writeBlocked;
8403928aee4356845252ac6b662d5c72c29903813eJake Slack
8503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** true if {@link SelectSet#destroyEndPoint(SelectChannelEndPoint)} has not been called */
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _open;
8703928aee4356845252ac6b662d5c72c29903813eJake Slack
8803928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile long _idleTimestamp;
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile boolean _checkIdle;
9003928aee4356845252ac6b662d5c72c29903813eJake Slack
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _interruptable;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _ishut;
9403928aee4356845252ac6b662d5c72c29903813eJake Slack
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime)
9703928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9903928aee4356845252ac6b662d5c72c29903813eJake Slack        super(channel, maxIdleTime);
10003928aee4356845252ac6b662d5c72c29903813eJake Slack
10103928aee4356845252ac6b662d5c72c29903813eJake Slack        _manager = selectSet.getManager();
10203928aee4356845252ac6b662d5c72c29903813eJake Slack        _selectSet = selectSet;
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        _state=STATE_UNDISPATCHED;
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        _onIdle=false;
10503928aee4356845252ac6b662d5c72c29903813eJake Slack        _open=true;
10603928aee4356845252ac6b662d5c72c29903813eJake Slack        _key = key;
10703928aee4356845252ac6b662d5c72c29903813eJake Slack
10803928aee4356845252ac6b662d5c72c29903813eJake Slack        setCheckForIdle(true);
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11003928aee4356845252ac6b662d5c72c29903813eJake Slack
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    public SelectionKey getSelectionKey()
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11403928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
11503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
11603928aee4356845252ac6b662d5c72c29903813eJake Slack            return _key;
11703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11903928aee4356845252ac6b662d5c72c29903813eJake Slack
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    public SelectorManager getSelectManager()
12203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _manager;
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12503928aee4356845252ac6b662d5c72c29903813eJake Slack
12603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Connection getConnection()
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connection;
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setConnection(Connection connection)
13403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        Connection old=_connection;
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        _connection=(AsyncConnection)connection;
13703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (old!=null && old!=_connection)
13803928aee4356845252ac6b662d5c72c29903813eJake Slack            _manager.endPointUpgraded(this,old);
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14003928aee4356845252ac6b662d5c72c29903813eJake Slack
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getIdleTimestamp()
14303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _idleTimestamp;
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14603928aee4356845252ac6b662d5c72c29903813eJake Slack
14703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Called by selectSet to schedule handling
14903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
15003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void schedule()
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15303928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
15403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
15503928aee4356845252ac6b662d5c72c29903813eJake Slack            // If there is no key, then do nothing
15603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_key == null || !_key.isValid())
15703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
15803928aee4356845252ac6b662d5c72c29903813eJake Slack                _readBlocked=false;
15903928aee4356845252ac6b662d5c72c29903813eJake Slack                _writeBlocked=false;
16003928aee4356845252ac6b662d5c72c29903813eJake Slack                this.notifyAll();
16103928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
16203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
16303928aee4356845252ac6b662d5c72c29903813eJake Slack
16403928aee4356845252ac6b662d5c72c29903813eJake Slack            // If there are threads dispatched reading and writing
16503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_readBlocked || _writeBlocked)
16603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
16703928aee4356845252ac6b662d5c72c29903813eJake Slack                // assert _dispatched;
16803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_readBlocked && _key.isReadable())
16903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _readBlocked=false;
17003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_writeBlocked && _key.isWritable())
17103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _writeBlocked=false;
17203928aee4356845252ac6b662d5c72c29903813eJake Slack
17303928aee4356845252ac6b662d5c72c29903813eJake Slack                // wake them up is as good as a dispatched.
17403928aee4356845252ac6b662d5c72c29903813eJake Slack                this.notifyAll();
17503928aee4356845252ac6b662d5c72c29903813eJake Slack
17603928aee4356845252ac6b662d5c72c29903813eJake Slack                // we are not interested in further selecting
17703928aee4356845252ac6b662d5c72c29903813eJake Slack                _key.interestOps(0);
17803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_state<STATE_DISPATCHED)
17903928aee4356845252ac6b662d5c72c29903813eJake Slack                    updateKey();
18003928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
18203928aee4356845252ac6b662d5c72c29903813eJake Slack
18303928aee4356845252ac6b662d5c72c29903813eJake Slack            // Remove writeable op
18403928aee4356845252ac6b662d5c72c29903813eJake Slack            if ((_key.readyOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE && (_key.interestOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE)
18503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
18603928aee4356845252ac6b662d5c72c29903813eJake Slack                // Remove writeable op
18703928aee4356845252ac6b662d5c72c29903813eJake Slack                _interestOps = _key.interestOps() & ~SelectionKey.OP_WRITE;
18803928aee4356845252ac6b662d5c72c29903813eJake Slack                _key.interestOps(_interestOps);
18903928aee4356845252ac6b662d5c72c29903813eJake Slack                _writable = true; // Once writable is in ops, only removed with dispatch.
19003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
19103928aee4356845252ac6b662d5c72c29903813eJake Slack
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            // If dispatched, then deregister interest
19303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_state>=STATE_DISPATCHED)
19403928aee4356845252ac6b662d5c72c29903813eJake Slack                _key.interestOps(0);
19503928aee4356845252ac6b662d5c72c29903813eJake Slack            else
19603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
19703928aee4356845252ac6b662d5c72c29903813eJake Slack                // other wise do the dispatch
19803928aee4356845252ac6b662d5c72c29903813eJake Slack                dispatch();
19903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_state>=STATE_DISPATCHED && !_selectSet.getManager().isDeferringInterestedOps0())
20003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
20103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _key.interestOps(0);
20203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
20303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20603928aee4356845252ac6b662d5c72c29903813eJake Slack
20703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void asyncDispatch()
20903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
21103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
21303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21403928aee4356845252ac6b662d5c72c29903813eJake Slack                case STATE_NEEDS_DISPATCH:
21503928aee4356845252ac6b662d5c72c29903813eJake Slack                case STATE_UNDISPATCHED:
21603928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatch();
21703928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
21803928aee4356845252ac6b662d5c72c29903813eJake Slack
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                case STATE_DISPATCHED:
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                case STATE_ASYNC:
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=STATE_ASYNC;
22203928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
22303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22603928aee4356845252ac6b662d5c72c29903813eJake Slack
22703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dispatch()
22903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(this)
23103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
23203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_state<=STATE_UNDISPATCHED)
23303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
23403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_onIdle)
23503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state = STATE_NEEDS_DISPATCH;
23603928aee4356845252ac6b662d5c72c29903813eJake Slack                else
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
23803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state = STATE_DISPATCHED;
23903928aee4356845252ac6b662d5c72c29903813eJake Slack                    boolean dispatched = _manager.dispatch(_handler);
24003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if(!dispatched)
24103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state = STATE_NEEDS_DISPATCH;
24303928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn("Dispatched Failed! "+this+" to "+_manager);
24403928aee4356845252ac6b662d5c72c29903813eJake Slack                        updateKey();
24503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
24603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
24703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
24803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
24903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25003928aee4356845252ac6b662d5c72c29903813eJake Slack
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
25303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Called when a dispatched thread is no longer handling the endpoint.
25403928aee4356845252ac6b662d5c72c29903813eJake Slack     * The selection key operations are updated.
25503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return If false is returned, the endpoint has been redispatched and
25603928aee4356845252ac6b662d5c72c29903813eJake Slack     * thread must keep handling the endpoint.
25703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
25803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean undispatch()
25903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
26103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
26203928aee4356845252ac6b662d5c72c29903813eJake Slack            switch(_state)
26303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
26403928aee4356845252ac6b662d5c72c29903813eJake Slack                case STATE_ASYNC:
26503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=STATE_DISPATCHED;
26603928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
26703928aee4356845252ac6b662d5c72c29903813eJake Slack
26803928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
26903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=STATE_UNDISPATCHED;
27003928aee4356845252ac6b662d5c72c29903813eJake Slack                    updateKey();
27103928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
27203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
27303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void cancelTimeout(Task task)
27803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        getSelectSet().cancelTimeout(task);
28003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28103928aee4356845252ac6b662d5c72c29903813eJake Slack
28203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void scheduleTimeout(Task task, long timeoutMs)
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28503928aee4356845252ac6b662d5c72c29903813eJake Slack        getSelectSet().scheduleTimeout(task,timeoutMs);
28603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28703928aee4356845252ac6b662d5c72c29903813eJake Slack
28803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setCheckForIdle(boolean check)
29003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (check)
29203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
29303928aee4356845252ac6b662d5c72c29903813eJake Slack            _idleTimestamp=System.currentTimeMillis();
29403928aee4356845252ac6b662d5c72c29903813eJake Slack            _checkIdle=true;
29503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
29603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
29703928aee4356845252ac6b662d5c72c29903813eJake Slack            _checkIdle=false;
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29903928aee4356845252ac6b662d5c72c29903813eJake Slack
30003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isCheckForIdle()
30203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _checkIdle;
30403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30503928aee4356845252ac6b662d5c72c29903813eJake Slack
30603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void notIdle()
30803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30903928aee4356845252ac6b662d5c72c29903813eJake Slack        _idleTimestamp=System.currentTimeMillis();
31003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
31103928aee4356845252ac6b662d5c72c29903813eJake Slack
31203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void checkIdleTimestamp(long now)
31403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (isCheckForIdle() && _maxIdleTime>0)
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
31703928aee4356845252ac6b662d5c72c29903813eJake Slack            final long idleForMs=now-_idleTimestamp;
31803928aee4356845252ac6b662d5c72c29903813eJake Slack
31903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (idleForMs>_maxIdleTime)
32003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
32103928aee4356845252ac6b662d5c72c29903813eJake Slack                // Don't idle out again until onIdleExpired task completes.
32203928aee4356845252ac6b662d5c72c29903813eJake Slack                setCheckForIdle(false);
32303928aee4356845252ac6b662d5c72c29903813eJake Slack                _manager.dispatch(new Runnable()
32403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
32503928aee4356845252ac6b662d5c72c29903813eJake Slack                    public void run()
32603928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
32703928aee4356845252ac6b662d5c72c29903813eJake Slack                        try
32803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
32903928aee4356845252ac6b662d5c72c29903813eJake Slack                            onIdleExpired(idleForMs);
33003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
33103928aee4356845252ac6b662d5c72c29903813eJake Slack                        finally
33203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                            setCheckForIdle(true);
33403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
33503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
33603928aee4356845252ac6b662d5c72c29903813eJake Slack                });
33703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34003928aee4356845252ac6b662d5c72c29903813eJake Slack
34103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
34203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void onIdleExpired(long idleForMs)
34303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
34503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34603928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized (this)
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
34803928aee4356845252ac6b662d5c72c29903813eJake Slack                _onIdle=true;
34903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35003928aee4356845252ac6b662d5c72c29903813eJake Slack
35103928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection.onIdleExpired(idleForMs);
35203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
35303928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
35403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
35503928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized (this)
35603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
35703928aee4356845252ac6b662d5c72c29903813eJake Slack                _onIdle=false;
35803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_state==STATE_NEEDS_DISPATCH)
35903928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatch();
36003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36303928aee4356845252ac6b662d5c72c29903813eJake Slack
36403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
36603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int fill(Buffer buffer) throws IOException
36703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36803928aee4356845252ac6b662d5c72c29903813eJake Slack        int fill=super.fill(buffer);
36903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (fill>0)
37003928aee4356845252ac6b662d5c72c29903813eJake Slack            notIdle();
37103928aee4356845252ac6b662d5c72c29903813eJake Slack        return fill;
37203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
37303928aee4356845252ac6b662d5c72c29903813eJake Slack
37403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
37603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
37703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37803928aee4356845252ac6b662d5c72c29903813eJake Slack        int l = super.flush(header, buffer, trailer);
37903928aee4356845252ac6b662d5c72c29903813eJake Slack
38003928aee4356845252ac6b662d5c72c29903813eJake Slack        // If there was something to write and it wasn't written, then we are not writable.
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (l==0 && ( header!=null && header.hasContent() || buffer!=null && buffer.hasContent() || trailer!=null && trailer.hasContent()))
38203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized (this)
38403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38503928aee4356845252ac6b662d5c72c29903813eJake Slack                _writable=false;
38603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_state<STATE_DISPATCHED)
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                    updateKey();
38803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
38903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39003928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (l>0)
39103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
39203928aee4356845252ac6b662d5c72c29903813eJake Slack            _writable=true;
39303928aee4356845252ac6b662d5c72c29903813eJake Slack            notIdle();
39403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39503928aee4356845252ac6b662d5c72c29903813eJake Slack        return l;
39603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39703928aee4356845252ac6b662d5c72c29903813eJake Slack
39803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
39903928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
40003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
40103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
40203928aee4356845252ac6b662d5c72c29903813eJake Slack    public int flush(Buffer buffer) throws IOException
40303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40403928aee4356845252ac6b662d5c72c29903813eJake Slack        int l = super.flush(buffer);
40503928aee4356845252ac6b662d5c72c29903813eJake Slack
40603928aee4356845252ac6b662d5c72c29903813eJake Slack        // If there was something to write and it wasn't written, then we are not writable.
40703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (l==0 && buffer!=null && buffer.hasContent())
40803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
40903928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized (this)
41003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                _writable=false;
41203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_state<STATE_DISPATCHED)
41303928aee4356845252ac6b662d5c72c29903813eJake Slack                    updateKey();
41403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
41503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
41603928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (l>0)
41703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41803928aee4356845252ac6b662d5c72c29903813eJake Slack            _writable=true;
41903928aee4356845252ac6b662d5c72c29903813eJake Slack            notIdle();
42003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42103928aee4356845252ac6b662d5c72c29903813eJake Slack
42203928aee4356845252ac6b662d5c72c29903813eJake Slack        return l;
42303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
42403928aee4356845252ac6b662d5c72c29903813eJake Slack
42503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
42603928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
42703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Allows thread to block waiting for further events.
42803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
42903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
43003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean blockReadable(long timeoutMs) throws IOException
43103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
43203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
43303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
43403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isInputShutdown())
43503928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new EofException();
43603928aee4356845252ac6b662d5c72c29903813eJake Slack
43703928aee4356845252ac6b662d5c72c29903813eJake Slack            long now=_selectSet.getNow();
43803928aee4356845252ac6b662d5c72c29903813eJake Slack            long end=now+timeoutMs;
43903928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean check=isCheckForIdle();
44003928aee4356845252ac6b662d5c72c29903813eJake Slack            setCheckForIdle(true);
44103928aee4356845252ac6b662d5c72c29903813eJake Slack            try
44203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
44303928aee4356845252ac6b662d5c72c29903813eJake Slack                _readBlocked=true;
44403928aee4356845252ac6b662d5c72c29903813eJake Slack                while (!isInputShutdown() && _readBlocked)
44503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
44603928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
44703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
44803928aee4356845252ac6b662d5c72c29903813eJake Slack                        updateKey();
44903928aee4356845252ac6b662d5c72c29903813eJake Slack                        this.wait(timeoutMs>0?(end-now):10000);
45003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
45103928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (final InterruptedException e)
45203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
45303928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn(e);
45403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_interruptable)
45503928aee4356845252ac6b662d5c72c29903813eJake Slack                            throw new InterruptedIOException(){{this.initCause(e);}};
45603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
45703928aee4356845252ac6b662d5c72c29903813eJake Slack                    finally
45803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
45903928aee4356845252ac6b662d5c72c29903813eJake Slack                        now=_selectSet.getNow();
46003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
46103928aee4356845252ac6b662d5c72c29903813eJake Slack
46203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_readBlocked && timeoutMs>0 && now>=end)
46303928aee4356845252ac6b662d5c72c29903813eJake Slack                        return false;
46403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
46503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46603928aee4356845252ac6b662d5c72c29903813eJake Slack            finally
46703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46803928aee4356845252ac6b662d5c72c29903813eJake Slack                _readBlocked=false;
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                setCheckForIdle(check);
47003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47203928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
47303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
47403928aee4356845252ac6b662d5c72c29903813eJake Slack
47503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
47603928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
47703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Allows thread to block waiting for further events.
47803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
47903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
48003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean blockWritable(long timeoutMs) throws IOException
48103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
48203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
48303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isOutputShutdown())
48503928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new EofException();
48603928aee4356845252ac6b662d5c72c29903813eJake Slack
48703928aee4356845252ac6b662d5c72c29903813eJake Slack            long now=_selectSet.getNow();
48803928aee4356845252ac6b662d5c72c29903813eJake Slack            long end=now+timeoutMs;
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean check=isCheckForIdle();
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            setCheckForIdle(true);
49103928aee4356845252ac6b662d5c72c29903813eJake Slack            try
49203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49303928aee4356845252ac6b662d5c72c29903813eJake Slack                _writeBlocked=true;
49403928aee4356845252ac6b662d5c72c29903813eJake Slack                while (_writeBlocked && !isOutputShutdown())
49503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
49603928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
49703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
49803928aee4356845252ac6b662d5c72c29903813eJake Slack                        updateKey();
49903928aee4356845252ac6b662d5c72c29903813eJake Slack                        this.wait(timeoutMs>0?(end-now):10000);
50003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
50103928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (final InterruptedException e)
50203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
50303928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn(e);
50403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_interruptable)
50503928aee4356845252ac6b662d5c72c29903813eJake Slack                            throw new InterruptedIOException(){{this.initCause(e);}};
50603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
50703928aee4356845252ac6b662d5c72c29903813eJake Slack                    finally
50803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
50903928aee4356845252ac6b662d5c72c29903813eJake Slack                        now=_selectSet.getNow();
51003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
51103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_writeBlocked && timeoutMs>0 && now>=end)
51203928aee4356845252ac6b662d5c72c29903813eJake Slack                        return false;
51303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
51403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
51503928aee4356845252ac6b662d5c72c29903813eJake Slack            finally
51603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51703928aee4356845252ac6b662d5c72c29903813eJake Slack                _writeBlocked=false;
51803928aee4356845252ac6b662d5c72c29903813eJake Slack                setCheckForIdle(check);
51903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
52003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
52103928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
52203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
52303928aee4356845252ac6b662d5c72c29903813eJake Slack
52403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
52503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Set the interruptable mode of the endpoint.
52603928aee4356845252ac6b662d5c72c29903813eJake Slack     * If set to false (default), then interrupts are assumed to be spurious
52703928aee4356845252ac6b662d5c72c29903813eJake Slack     * and blocking operations continue unless the endpoint has been closed.
52803928aee4356845252ac6b662d5c72c29903813eJake Slack     * If true, then interrupts of blocking operations result in InterruptedIOExceptions
52903928aee4356845252ac6b662d5c72c29903813eJake Slack     * being thrown.
53003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param interupable
53103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
53203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setInterruptable(boolean interupable)
53303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
53403928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
53503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
53603928aee4356845252ac6b662d5c72c29903813eJake Slack            _interruptable=interupable;
53703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
53903928aee4356845252ac6b662d5c72c29903813eJake Slack
54003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
54103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isInterruptable()
54203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
54303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _interruptable;
54403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
54503928aee4356845252ac6b662d5c72c29903813eJake Slack
54603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
54703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
54803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite()
54903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
55003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void scheduleWrite()
55103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
55203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_writable)
55303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("Required scheduleWrite {}",this);
55403928aee4356845252ac6b662d5c72c29903813eJake Slack
55503928aee4356845252ac6b662d5c72c29903813eJake Slack        _writable=false;
55603928aee4356845252ac6b662d5c72c29903813eJake Slack        updateKey();
55703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
55803928aee4356845252ac6b662d5c72c29903813eJake Slack
55903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
56003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isWritable()
56103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
56203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _writable;
56303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
56403928aee4356845252ac6b662d5c72c29903813eJake Slack
56503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
56603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean hasProgressed()
56703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
56803928aee4356845252ac6b662d5c72c29903813eJake Slack        return false;
56903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
57003928aee4356845252ac6b662d5c72c29903813eJake Slack
57103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
57203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
57303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Updates selection key. Adds operations types to the selection key as needed. No operations
57403928aee4356845252ac6b662d5c72c29903813eJake Slack     * are removed as this is only done during dispatch. This method records the new key and
57503928aee4356845252ac6b662d5c72c29903813eJake Slack     * schedules a call to doUpdateKey to do the keyChange
57603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
57703928aee4356845252ac6b662d5c72c29903813eJake Slack    private void updateKey()
57803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
57903928aee4356845252ac6b662d5c72c29903813eJake Slack        final boolean changed;
58003928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
58103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
58203928aee4356845252ac6b662d5c72c29903813eJake Slack            int current_ops=-1;
58303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (getChannel().isOpen())
58403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
58503928aee4356845252ac6b662d5c72c29903813eJake Slack                boolean read_interest = _readBlocked || (_state<STATE_DISPATCHED && !_connection.isSuspended());
58603928aee4356845252ac6b662d5c72c29903813eJake Slack                boolean write_interest= _writeBlocked || (_state<STATE_DISPATCHED && !_writable);
58703928aee4356845252ac6b662d5c72c29903813eJake Slack
58803928aee4356845252ac6b662d5c72c29903813eJake Slack                _interestOps =
58903928aee4356845252ac6b662d5c72c29903813eJake Slack                    ((!_socket.isInputShutdown() && read_interest ) ? SelectionKey.OP_READ  : 0)
59003928aee4356845252ac6b662d5c72c29903813eJake Slack                |   ((!_socket.isOutputShutdown()&& write_interest) ? SelectionKey.OP_WRITE : 0);
59103928aee4356845252ac6b662d5c72c29903813eJake Slack                try
59203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
59303928aee4356845252ac6b662d5c72c29903813eJake Slack                    current_ops = ((_key!=null && _key.isValid())?_key.interestOps():-1);
59403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
59503928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Exception e)
59603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
59703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _key=null;
59803928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
59903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
60003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
60103928aee4356845252ac6b662d5c72c29903813eJake Slack            changed=_interestOps!=current_ops;
60203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
60303928aee4356845252ac6b662d5c72c29903813eJake Slack
60403928aee4356845252ac6b662d5c72c29903813eJake Slack        if(changed)
60503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
60603928aee4356845252ac6b662d5c72c29903813eJake Slack            _selectSet.addChange(this);
60703928aee4356845252ac6b662d5c72c29903813eJake Slack            _selectSet.wakeup();
60803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
60903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
61003928aee4356845252ac6b662d5c72c29903813eJake Slack
61103928aee4356845252ac6b662d5c72c29903813eJake Slack
61203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
61303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
61403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Synchronize the interestOps with the actual key. Call is scheduled by a call to updateKey
61503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
61603928aee4356845252ac6b662d5c72c29903813eJake Slack    void doUpdateKey()
61703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
61803928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
61903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (getChannel().isOpen())
62103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
62203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_interestOps>0)
62303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
62403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_key==null || !_key.isValid())
62503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
62603928aee4356845252ac6b662d5c72c29903813eJake Slack                        SelectableChannel sc = (SelectableChannel)getChannel();
62703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (sc.isRegistered())
62803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
62903928aee4356845252ac6b662d5c72c29903813eJake Slack                            updateKey();
63003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
63103928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
63203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
63303928aee4356845252ac6b662d5c72c29903813eJake Slack                            try
63403928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
63503928aee4356845252ac6b662d5c72c29903813eJake Slack                                _key=((SelectableChannel)getChannel()).register(_selectSet.getSelector(),_interestOps,this);
63603928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
63703928aee4356845252ac6b662d5c72c29903813eJake Slack                            catch (Exception e)
63803928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
63903928aee4356845252ac6b662d5c72c29903813eJake Slack                                LOG.ignore(e);
64003928aee4356845252ac6b662d5c72c29903813eJake Slack                                if (_key!=null && _key.isValid())
64103928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
64203928aee4356845252ac6b662d5c72c29903813eJake Slack                                    _key.cancel();
64303928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
64403928aee4356845252ac6b662d5c72c29903813eJake Slack
64503928aee4356845252ac6b662d5c72c29903813eJake Slack                                if (_open)
64603928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
64703928aee4356845252ac6b662d5c72c29903813eJake Slack                                    _selectSet.destroyEndPoint(this);
64803928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
64903928aee4356845252ac6b662d5c72c29903813eJake Slack                                _open=false;
65003928aee4356845252ac6b662d5c72c29903813eJake Slack                                _key = null;
65103928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
65203928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
65303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
65403928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
65503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
65603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _key.interestOps(_interestOps);
65703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
65803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
65903928aee4356845252ac6b662d5c72c29903813eJake Slack                else
66003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
66103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_key!=null && _key.isValid())
66203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _key.interestOps(0);
66303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
66403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _key=null;
66503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
66603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
66703928aee4356845252ac6b662d5c72c29903813eJake Slack            else
66803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
66903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_key!=null && _key.isValid())
67003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _key.cancel();
67103928aee4356845252ac6b662d5c72c29903813eJake Slack
67203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_open)
67303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
67403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _open=false;
67503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _selectSet.destroyEndPoint(this);
67603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
67703928aee4356845252ac6b662d5c72c29903813eJake Slack                _key = null;
67803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
67903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
68003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
68103928aee4356845252ac6b662d5c72c29903813eJake Slack
68203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
68303928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
68403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
68503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void handle()
68603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
68703928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean dispatched=true;
68803928aee4356845252ac6b662d5c72c29903813eJake Slack        try
68903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
69003928aee4356845252ac6b662d5c72c29903813eJake Slack            while(dispatched)
69103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
69203928aee4356845252ac6b662d5c72c29903813eJake Slack                try
69303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
69403928aee4356845252ac6b662d5c72c29903813eJake Slack                    while(true)
69503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
69603928aee4356845252ac6b662d5c72c29903813eJake Slack                        final AsyncConnection next = (AsyncConnection)_connection.handle();
69703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (next!=_connection)
69803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
69903928aee4356845252ac6b662d5c72c29903813eJake Slack                            LOG.debug("{} replaced {}",next,_connection);
70003928aee4356845252ac6b662d5c72c29903813eJake Slack                            Connection old=_connection;
70103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _connection=next;
70203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _manager.endPointUpgraded(this,old);
70303928aee4356845252ac6b662d5c72c29903813eJake Slack                            continue;
70403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
70503928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
70603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
70703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
70803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (ClosedChannelException e)
70903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
71003928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
71103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
71203928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (EofException e)
71303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
71403928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug("EOF", e);
71503928aee4356845252ac6b662d5c72c29903813eJake Slack                    try{close();}
71603928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch(IOException e2){LOG.ignore(e2);}
71703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
71803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (IOException e)
71903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
72003928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn(e.toString());
72103928aee4356845252ac6b662d5c72c29903813eJake Slack                    try{close();}
72203928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch(IOException e2){LOG.ignore(e2);}
72303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
72403928aee4356845252ac6b662d5c72c29903813eJake Slack                catch (Throwable e)
72503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
72603928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn("handle failed", e);
72703928aee4356845252ac6b662d5c72c29903813eJake Slack                    try{close();}
72803928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch(IOException e2){LOG.ignore(e2);}
72903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
73003928aee4356845252ac6b662d5c72c29903813eJake Slack                finally
73103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
73203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!_ishut && isInputShutdown() && isOpen())
73303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
73403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _ishut=true;
73503928aee4356845252ac6b662d5c72c29903813eJake Slack                        try
73603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
73703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _connection.onInputShutdown();
73803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
73903928aee4356845252ac6b662d5c72c29903813eJake Slack                        catch(Throwable x)
74003928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
74103928aee4356845252ac6b662d5c72c29903813eJake Slack                            LOG.warn("onInputShutdown failed", x);
74203928aee4356845252ac6b662d5c72c29903813eJake Slack                            try{close();}
74303928aee4356845252ac6b662d5c72c29903813eJake Slack                            catch(IOException e2){LOG.ignore(e2);}
74403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
74503928aee4356845252ac6b662d5c72c29903813eJake Slack                        finally
74603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
74703928aee4356845252ac6b662d5c72c29903813eJake Slack                            updateKey();
74803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
74903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
75003928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatched=!undispatch();
75103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
75203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
75303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
75403928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
75503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
75603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (dispatched)
75703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
75803928aee4356845252ac6b662d5c72c29903813eJake Slack                dispatched=!undispatch();
75903928aee4356845252ac6b662d5c72c29903813eJake Slack                while (dispatched)
76003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
76103928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.warn("SCEP.run() finally DISPATCHED");
76203928aee4356845252ac6b662d5c72c29903813eJake Slack                    dispatched=!undispatch();
76303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
76403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
76503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
76603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
76703928aee4356845252ac6b662d5c72c29903813eJake Slack
76803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
76903928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
77003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.io.nio.ChannelEndPoint#close()
77103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
77203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
77303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void close() throws IOException
77403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
77503928aee4356845252ac6b662d5c72c29903813eJake Slack        // On unix systems there is a JVM issue that if you cancel before closing, it can
77603928aee4356845252ac6b662d5c72c29903813eJake Slack        // cause the selector to block waiting for a channel to close and that channel can
77703928aee4356845252ac6b662d5c72c29903813eJake Slack        // block waiting for the remote end.  But on windows, if you don't cancel before a
77803928aee4356845252ac6b662d5c72c29903813eJake Slack        // close, then the selector can block anyway!
77903928aee4356845252ac6b662d5c72c29903813eJake Slack        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318
78003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (WORK_AROUND_JVM_BUG_6346658)
78103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
78203928aee4356845252ac6b662d5c72c29903813eJake Slack            try
78303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
78403928aee4356845252ac6b662d5c72c29903813eJake Slack                SelectionKey key = _key;
78503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key!=null)
78603928aee4356845252ac6b662d5c72c29903813eJake Slack                    key.cancel();
78703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
78803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Throwable e)
78903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
79003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
79103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
79203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
79303928aee4356845252ac6b662d5c72c29903813eJake Slack
79403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
79503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
79603928aee4356845252ac6b662d5c72c29903813eJake Slack            super.close();
79703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
79803928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (IOException e)
79903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
80003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
80103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
80203928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
80303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
80403928aee4356845252ac6b662d5c72c29903813eJake Slack            updateKey();
80503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
80603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
80703928aee4356845252ac6b662d5c72c29903813eJake Slack
80803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
80903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
81003928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
81103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
81203928aee4356845252ac6b662d5c72c29903813eJake Slack        // Do NOT use synchronized (this)
81303928aee4356845252ac6b662d5c72c29903813eJake Slack        // because it's very easy to deadlock when debugging is enabled.
81403928aee4356845252ac6b662d5c72c29903813eJake Slack        // We do a best effort to print the right toString() and that's it.
81503928aee4356845252ac6b662d5c72c29903813eJake Slack        SelectionKey key = _key;
81603928aee4356845252ac6b662d5c72c29903813eJake Slack        String keyString = "";
81703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (key != null)
81803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
81903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (key.isValid())
82003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
82103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.isReadable())
82203928aee4356845252ac6b662d5c72c29903813eJake Slack                    keyString += "r";
82303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.isWritable())
82403928aee4356845252ac6b662d5c72c29903813eJake Slack                    keyString += "w";
82503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
82603928aee4356845252ac6b662d5c72c29903813eJake Slack            else
82703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
82803928aee4356845252ac6b662d5c72c29903813eJake Slack                keyString += "!";
82903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
83003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
83103928aee4356845252ac6b662d5c72c29903813eJake Slack        else
83203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
83303928aee4356845252ac6b662d5c72c29903813eJake Slack            keyString += "-";
83403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
83503928aee4356845252ac6b662d5c72c29903813eJake Slack        return String.format("SCEP@%x{l(%s)<->r(%s),s=%d,open=%b,ishut=%b,oshut=%b,rb=%b,wb=%b,w=%b,i=%d%s}-{%s}",
83603928aee4356845252ac6b662d5c72c29903813eJake Slack                hashCode(),
83703928aee4356845252ac6b662d5c72c29903813eJake Slack                _socket.getRemoteSocketAddress(),
83803928aee4356845252ac6b662d5c72c29903813eJake Slack                _socket.getLocalSocketAddress(),
83903928aee4356845252ac6b662d5c72c29903813eJake Slack                _state,
84003928aee4356845252ac6b662d5c72c29903813eJake Slack                isOpen(),
84103928aee4356845252ac6b662d5c72c29903813eJake Slack                isInputShutdown(),
84203928aee4356845252ac6b662d5c72c29903813eJake Slack                isOutputShutdown(),
84303928aee4356845252ac6b662d5c72c29903813eJake Slack                _readBlocked,
84403928aee4356845252ac6b662d5c72c29903813eJake Slack                _writeBlocked,
84503928aee4356845252ac6b662d5c72c29903813eJake Slack                _writable,
84603928aee4356845252ac6b662d5c72c29903813eJake Slack                _interestOps,
84703928aee4356845252ac6b662d5c72c29903813eJake Slack                keyString,
84803928aee4356845252ac6b662d5c72c29903813eJake Slack                _connection);
84903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
85003928aee4356845252ac6b662d5c72c29903813eJake Slack
85103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
85203928aee4356845252ac6b662d5c72c29903813eJake Slack    public SelectSet getSelectSet()
85303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
85403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _selectSet;
85503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
85603928aee4356845252ac6b662d5c72c29903813eJake Slack
85703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
85803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
85903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Don't set the SoTimeout
86003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.io.nio.ChannelEndPoint#setMaxIdleTime(int)
86103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
86203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
86303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMaxIdleTime(int timeMs) throws IOException
86403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
86503928aee4356845252ac6b662d5c72c29903813eJake Slack        _maxIdleTime=timeMs;
86603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
86703928aee4356845252ac6b662d5c72c29903813eJake Slack
86803928aee4356845252ac6b662d5c72c29903813eJake Slack}
869