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.server.nio;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.InetSocketAddress;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.Socket;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.ByteChannel;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.SelectionKey;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.ServerSocketChannel;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.nio.channels.SocketChannel;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
2903928aee4356845252ac6b662d5c72c29903813eJake Slack
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpException;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.ConnectedEndPoint;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Connection;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.nio.ChannelEndPoint;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.BlockingHttpConnection;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.ConcurrentHashSet;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
4203928aee4356845252ac6b662d5c72c29903813eJake Slack
4303928aee4356845252ac6b662d5c72c29903813eJake Slack
4403928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------------------------- */
4503928aee4356845252ac6b662d5c72c29903813eJake Slack/**  Blocking NIO connector.
4603928aee4356845252ac6b662d5c72c29903813eJake Slack * This connector uses efficient NIO buffers with a traditional blocking thread model.
4703928aee4356845252ac6b662d5c72c29903813eJake Slack * Direct NIO buffers are used and a thread is allocated per connections.
4803928aee4356845252ac6b662d5c72c29903813eJake Slack *
4903928aee4356845252ac6b662d5c72c29903813eJake Slack * This connector is best used when there are a few very active connections.
5003928aee4356845252ac6b662d5c72c29903813eJake Slack *
5103928aee4356845252ac6b662d5c72c29903813eJake Slack * @org.apache.xbean.XBean element="blockingNioConnector" description="Creates a blocking NIO based socket connector"
5203928aee4356845252ac6b662d5c72c29903813eJake Slack *
5303928aee4356845252ac6b662d5c72c29903813eJake Slack *
5403928aee4356845252ac6b662d5c72c29903813eJake Slack *
5503928aee4356845252ac6b662d5c72c29903813eJake Slack */
5603928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class BlockingChannelConnector extends AbstractNIOConnector
5703928aee4356845252ac6b662d5c72c29903813eJake Slack{
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(BlockingChannelConnector.class);
5903928aee4356845252ac6b662d5c72c29903813eJake Slack
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    private transient ServerSocketChannel _acceptChannel;
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Set<BlockingChannelEndPoint> _endpoints = new ConcurrentHashSet<BlockingChannelEndPoint>();
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Constructor.
6603928aee4356845252ac6b662d5c72c29903813eJake Slack     *
6703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    public BlockingChannelConnector()
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7103928aee4356845252ac6b662d5c72c29903813eJake Slack
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getConnection()
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _acceptChannel;
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7703928aee4356845252ac6b662d5c72c29903813eJake Slack
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
8003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.AbstractConnector#doStart()
8103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStart() throws Exception
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8503928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
8603928aee4356845252ac6b662d5c72c29903813eJake Slack        getThreadPool().dispatch(new Runnable()
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
8803928aee4356845252ac6b662d5c72c29903813eJake Slack
8903928aee4356845252ac6b662d5c72c29903813eJake Slack            public void run()
9003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
9103928aee4356845252ac6b662d5c72c29903813eJake Slack                while (isRunning())
9203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
9303928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
9403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
9503928aee4356845252ac6b662d5c72c29903813eJake Slack                        Thread.sleep(400);
9603928aee4356845252ac6b662d5c72c29903813eJake Slack                        long now=System.currentTimeMillis();
9703928aee4356845252ac6b662d5c72c29903813eJake Slack                        for (BlockingChannelEndPoint endp : _endpoints)
9803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
9903928aee4356845252ac6b662d5c72c29903813eJake Slack                            endp.checkIdleTimestamp(now);
10003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
10103928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
10203928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch(InterruptedException e)
10303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
10403928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
10503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
10603928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch(Exception e)
10703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
10803928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn(e);
10903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
11003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
11103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
11203928aee4356845252ac6b662d5c72c29903813eJake Slack
11303928aee4356845252ac6b662d5c72c29903813eJake Slack        });
11403928aee4356845252ac6b662d5c72c29903813eJake Slack
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11603928aee4356845252ac6b662d5c72c29903813eJake Slack
11703928aee4356845252ac6b662d5c72c29903813eJake Slack
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void open() throws IOException
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        // Create a new server socket and set to non blocking mode
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        _acceptChannel= ServerSocketChannel.open();
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        _acceptChannel.configureBlocking(true);
12403928aee4356845252ac6b662d5c72c29903813eJake Slack
12503928aee4356845252ac6b662d5c72c29903813eJake Slack        // Bind the server socket to the local host and port
12603928aee4356845252ac6b662d5c72c29903813eJake Slack        InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
12703928aee4356845252ac6b662d5c72c29903813eJake Slack        _acceptChannel.socket().bind(addr,getAcceptQueueSize());
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12903928aee4356845252ac6b662d5c72c29903813eJake Slack
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void close() throws IOException
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_acceptChannel != null)
13403928aee4356845252ac6b662d5c72c29903813eJake Slack            _acceptChannel.close();
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        _acceptChannel=null;
13603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13703928aee4356845252ac6b662d5c72c29903813eJake Slack
13803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void accept(int acceptorID)
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    	throws IOException, InterruptedException
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14303928aee4356845252ac6b662d5c72c29903813eJake Slack        SocketChannel channel = _acceptChannel.accept();
14403928aee4356845252ac6b662d5c72c29903813eJake Slack        channel.configureBlocking(true);
14503928aee4356845252ac6b662d5c72c29903813eJake Slack        Socket socket=channel.socket();
14603928aee4356845252ac6b662d5c72c29903813eJake Slack        configure(socket);
14703928aee4356845252ac6b662d5c72c29903813eJake Slack
14803928aee4356845252ac6b662d5c72c29903813eJake Slack        BlockingChannelEndPoint connection=new BlockingChannelEndPoint(channel);
14903928aee4356845252ac6b662d5c72c29903813eJake Slack        connection.dispatch();
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15103928aee4356845252ac6b662d5c72c29903813eJake Slack
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void customize(EndPoint endpoint, Request request)
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15703928aee4356845252ac6b662d5c72c29903813eJake Slack        super.customize(endpoint, request);
15803928aee4356845252ac6b662d5c72c29903813eJake Slack        endpoint.setMaxIdleTime(_maxIdleTime);
15903928aee4356845252ac6b662d5c72c29903813eJake Slack        configure(((SocketChannel)endpoint.getTransport()).socket());
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16103928aee4356845252ac6b662d5c72c29903813eJake Slack
16203928aee4356845252ac6b662d5c72c29903813eJake Slack
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
16403928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getLocalPort()
16503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_acceptChannel==null || !_acceptChannel.isOpen())
16703928aee4356845252ac6b662d5c72c29903813eJake Slack            return -1;
16803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _acceptChannel.socket().getLocalPort();
16903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17003928aee4356845252ac6b662d5c72c29903813eJake Slack
17103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    private class BlockingChannelEndPoint extends ChannelEndPoint implements Runnable, ConnectedEndPoint
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        private Connection _connection;
17703928aee4356845252ac6b662d5c72c29903813eJake Slack        private int _timeout;
17803928aee4356845252ac6b662d5c72c29903813eJake Slack        private volatile long _idleTimestamp;
17903928aee4356845252ac6b662d5c72c29903813eJake Slack
18003928aee4356845252ac6b662d5c72c29903813eJake Slack        BlockingChannelEndPoint(ByteChannel channel)
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            throws IOException
18203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
18303928aee4356845252ac6b662d5c72c29903813eJake Slack            super(channel,BlockingChannelConnector.this._maxIdleTime);
18403928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection = new BlockingHttpConnection(BlockingChannelConnector.this,this,getServer());
18503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
18603928aee4356845252ac6b662d5c72c29903813eJake Slack
18703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        /** Get the connection.
18903928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return the connection
19003928aee4356845252ac6b662d5c72c29903813eJake Slack         */
19103928aee4356845252ac6b662d5c72c29903813eJake Slack        public Connection getConnection()
19203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _connection;
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19503928aee4356845252ac6b662d5c72c29903813eJake Slack
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setConnection(Connection connection)
19803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19903928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection=connection;
20003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20103928aee4356845252ac6b662d5c72c29903813eJake Slack
20203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        public void checkIdleTimestamp(long now)
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_idleTimestamp!=0 && _timeout>0 && now>(_idleTimestamp+_timeout))
20603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
20703928aee4356845252ac6b662d5c72c29903813eJake Slack                idleExpired();
20803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
21003928aee4356845252ac6b662d5c72c29903813eJake Slack
21103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
21203928aee4356845252ac6b662d5c72c29903813eJake Slack        protected void idleExpired()
21303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21403928aee4356845252ac6b662d5c72c29903813eJake Slack            try
21503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21603928aee4356845252ac6b662d5c72c29903813eJake Slack                super.close();
21703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
21803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IOException e)
21903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
22103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22303928aee4356845252ac6b662d5c72c29903813eJake Slack
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
22503928aee4356845252ac6b662d5c72c29903813eJake Slack        void dispatch() throws IOException
22603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!getThreadPool().dispatch(this))
22803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
22903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("dispatch failed for  {}",_connection);
23003928aee4356845252ac6b662d5c72c29903813eJake Slack                super.close();
23103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
23203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
23303928aee4356845252ac6b662d5c72c29903813eJake Slack
23403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
23503928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
23603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see org.eclipse.jetty.io.nio.ChannelEndPoint#fill(org.eclipse.jetty.io.Buffer)
23703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
23803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
23903928aee4356845252ac6b662d5c72c29903813eJake Slack        public int fill(Buffer buffer) throws IOException
24003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
24103928aee4356845252ac6b662d5c72c29903813eJake Slack            _idleTimestamp=System.currentTimeMillis();
24203928aee4356845252ac6b662d5c72c29903813eJake Slack            return super.fill(buffer);
24303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
24403928aee4356845252ac6b662d5c72c29903813eJake Slack
24503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
24603928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
24703928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see org.eclipse.jetty.io.nio.ChannelEndPoint#flush(org.eclipse.jetty.io.Buffer)
24803928aee4356845252ac6b662d5c72c29903813eJake Slack         */
24903928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
25003928aee4356845252ac6b662d5c72c29903813eJake Slack        public int flush(Buffer buffer) throws IOException
25103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
25203928aee4356845252ac6b662d5c72c29903813eJake Slack            _idleTimestamp=System.currentTimeMillis();
25303928aee4356845252ac6b662d5c72c29903813eJake Slack            return super.flush(buffer);
25403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
25503928aee4356845252ac6b662d5c72c29903813eJake Slack
25603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
25703928aee4356845252ac6b662d5c72c29903813eJake Slack        /**
25803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see org.eclipse.jetty.io.nio.ChannelEndPoint#flush(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer)
25903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
26003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
26103928aee4356845252ac6b662d5c72c29903813eJake Slack        public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
26203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
26303928aee4356845252ac6b662d5c72c29903813eJake Slack            _idleTimestamp=System.currentTimeMillis();
26403928aee4356845252ac6b662d5c72c29903813eJake Slack            return super.flush(header,buffer,trailer);
26503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26603928aee4356845252ac6b662d5c72c29903813eJake Slack
26703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
26803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void run()
26903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
27003928aee4356845252ac6b662d5c72c29903813eJake Slack            try
27103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
27203928aee4356845252ac6b662d5c72c29903813eJake Slack                _timeout=getMaxIdleTime();
27303928aee4356845252ac6b662d5c72c29903813eJake Slack                connectionOpened(_connection);
27403928aee4356845252ac6b662d5c72c29903813eJake Slack                _endpoints.add(this);
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack                while (isOpen())
27703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
27803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _idleTimestamp=System.currentTimeMillis();
27903928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_connection.isIdle())
28003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
28103928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (getServer().getThreadPool().isLowOnThreads())
28203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
28303928aee4356845252ac6b662d5c72c29903813eJake Slack                            int lrmit = getLowResourcesMaxIdleTime();
28403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (lrmit>=0 && _timeout!= lrmit)
28503928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
28603928aee4356845252ac6b662d5c72c29903813eJake Slack                                _timeout=lrmit;
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
28803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
28903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
29003928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
29103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
29203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_timeout!=getMaxIdleTime())
29303928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
29403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _timeout=getMaxIdleTime();
29503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
29603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
29703928aee4356845252ac6b662d5c72c29903813eJake Slack
29803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connection = _connection.handle();
29903928aee4356845252ac6b662d5c72c29903813eJake Slack
30003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
30103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
30203928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (EofException e)
30303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
30403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("EOF", e);
30503928aee4356845252ac6b662d5c72c29903813eJake Slack                try{BlockingChannelEndPoint.this.close();}
30603928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
30703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
30803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (HttpException e)
30903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("BAD", e);
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                try{super.close();}
31203928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
31303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31403928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Throwable e)
31503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31603928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("handle failed",e);
31703928aee4356845252ac6b662d5c72c29903813eJake Slack                try{super.close();}
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
31903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32003928aee4356845252ac6b662d5c72c29903813eJake Slack            finally
32103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
32203928aee4356845252ac6b662d5c72c29903813eJake Slack                connectionClosed(_connection);
32303928aee4356845252ac6b662d5c72c29903813eJake Slack                _endpoints.remove(this);
32403928aee4356845252ac6b662d5c72c29903813eJake Slack
32503928aee4356845252ac6b662d5c72c29903813eJake Slack                // wait for client to close, but if not, close ourselves.
32603928aee4356845252ac6b662d5c72c29903813eJake Slack                try
32703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
32803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!_socket.isClosed())
32903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
33003928aee4356845252ac6b662d5c72c29903813eJake Slack                        long timestamp=System.currentTimeMillis();
33103928aee4356845252ac6b662d5c72c29903813eJake Slack                        int max_idle=getMaxIdleTime();
33203928aee4356845252ac6b662d5c72c29903813eJake Slack
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _socket.setSoTimeout(getMaxIdleTime());
33403928aee4356845252ac6b662d5c72c29903813eJake Slack                        int c=0;
33503928aee4356845252ac6b662d5c72c29903813eJake Slack                        do
33603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
33703928aee4356845252ac6b662d5c72c29903813eJake Slack                            c = _socket.getInputStream().read();
33803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
33903928aee4356845252ac6b662d5c72c29903813eJake Slack                        while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
34003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!_socket.isClosed())
34103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _socket.close();
34203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
34303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
34403928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e)
34503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
34603928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
34703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
34803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
34903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
35003928aee4356845252ac6b662d5c72c29903813eJake Slack
35103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
35203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
35303928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
35403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
35503928aee4356845252ac6b662d5c72c29903813eJake Slack            return String.format("BCEP@%x{l(%s)<->r(%s),open=%b,ishut=%b,oshut=%b}-{%s}",
35603928aee4356845252ac6b662d5c72c29903813eJake Slack                    hashCode(),
35703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _socket.getRemoteSocketAddress(),
35803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _socket.getLocalSocketAddress(),
35903928aee4356845252ac6b662d5c72c29903813eJake Slack                    isOpen(),
36003928aee4356845252ac6b662d5c72c29903813eJake Slack                    isInputShutdown(),
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                    isOutputShutdown(),
36203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connection);
36303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36403928aee4356845252ac6b662d5c72c29903813eJake Slack
36503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36603928aee4356845252ac6b662d5c72c29903813eJake Slack}
367