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.bio;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.InetAddress;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.ServerSocket;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.Socket;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.SocketException;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
2803928aee4356845252ac6b662d5c72c29903813eJake Slack
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpException;
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.EndPoint;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.bio.SocketEndPoint;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractConnector;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.BlockingHttpConnection;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.component.AggregateLifeCycle;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
4303928aee4356845252ac6b662d5c72c29903813eJake Slack
4403928aee4356845252ac6b662d5c72c29903813eJake Slack
4503928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------------------------- */
4603928aee4356845252ac6b662d5c72c29903813eJake Slack/**  Socket Connector.
4703928aee4356845252ac6b662d5c72c29903813eJake Slack * This connector implements a traditional blocking IO and threading model.
4803928aee4356845252ac6b662d5c72c29903813eJake Slack * Normal JRE sockets are used and a thread is allocated per connection.
4903928aee4356845252ac6b662d5c72c29903813eJake Slack * Buffers are managed so that large buffers are only allocated to active connections.
5003928aee4356845252ac6b662d5c72c29903813eJake Slack *
5103928aee4356845252ac6b662d5c72c29903813eJake Slack * This Connector should only be used if NIO is not available.
5203928aee4356845252ac6b662d5c72c29903813eJake Slack *
5303928aee4356845252ac6b662d5c72c29903813eJake Slack * @org.apache.xbean.XBean element="bioConnector" description="Creates a BIO based socket connector"
5403928aee4356845252ac6b662d5c72c29903813eJake Slack *
5503928aee4356845252ac6b662d5c72c29903813eJake Slack *
5603928aee4356845252ac6b662d5c72c29903813eJake Slack */
5703928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class SocketConnector extends AbstractConnector
5803928aee4356845252ac6b662d5c72c29903813eJake Slack{
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(SocketConnector.class);
6003928aee4356845252ac6b662d5c72c29903813eJake Slack
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected ServerSocket _serverSocket;
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    protected final Set<EndPoint> _connections;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected volatile int _localPort=-1;
6403928aee4356845252ac6b662d5c72c29903813eJake Slack
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Constructor.
6703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
6803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    public SocketConnector()
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7103928aee4356845252ac6b662d5c72c29903813eJake Slack        _connections=new HashSet<EndPoint>();
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7303928aee4356845252ac6b662d5c72c29903813eJake Slack
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getConnection()
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _serverSocket;
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7903928aee4356845252ac6b662d5c72c29903813eJake Slack
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void open() throws IOException
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8303928aee4356845252ac6b662d5c72c29903813eJake Slack        // Create a new server socket and set to non blocking mode
8403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_serverSocket==null || _serverSocket.isClosed())
8503928aee4356845252ac6b662d5c72c29903813eJake Slack        _serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
8603928aee4356845252ac6b662d5c72c29903813eJake Slack        _serverSocket.setReuseAddress(getReuseAddress());
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        _localPort=_serverSocket.getLocalPort();
8803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_localPort<=0)
8903928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("port not allocated for "+this);
9003928aee4356845252ac6b662d5c72c29903813eJake Slack
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9203928aee4356845252ac6b662d5c72c29903813eJake Slack
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9603928aee4356845252ac6b662d5c72c29903813eJake Slack        ServerSocket ss= host==null?
9703928aee4356845252ac6b662d5c72c29903813eJake Slack            new ServerSocket(port,backlog):
9803928aee4356845252ac6b662d5c72c29903813eJake Slack            new ServerSocket(port,backlog,InetAddress.getByName(host));
9903928aee4356845252ac6b662d5c72c29903813eJake Slack
10003928aee4356845252ac6b662d5c72c29903813eJake Slack        return ss;
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10203928aee4356845252ac6b662d5c72c29903813eJake Slack
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void close() throws IOException
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_serverSocket!=null)
10703928aee4356845252ac6b662d5c72c29903813eJake Slack            _serverSocket.close();
10803928aee4356845252ac6b662d5c72c29903813eJake Slack        _serverSocket=null;
10903928aee4356845252ac6b662d5c72c29903813eJake Slack        _localPort=-2;
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11103928aee4356845252ac6b662d5c72c29903813eJake Slack
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void accept(int acceptorID)
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    	throws IOException, InterruptedException
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11703928aee4356845252ac6b662d5c72c29903813eJake Slack        Socket socket = _serverSocket.accept();
11803928aee4356845252ac6b662d5c72c29903813eJake Slack        configure(socket);
11903928aee4356845252ac6b662d5c72c29903813eJake Slack
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        ConnectorEndPoint connection=new ConnectorEndPoint(socket);
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        connection.dispatch();
12203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12303928aee4356845252ac6b662d5c72c29903813eJake Slack
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
12503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
12603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Allows subclass to override Conection if required.
12703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Connection newConnection(EndPoint endpoint)
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        return new BlockingHttpConnection(this, endpoint, getServer());
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13203928aee4356845252ac6b662d5c72c29903813eJake Slack
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
13403928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
13503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void customize(EndPoint endpoint, Request request)
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13803928aee4356845252ac6b662d5c72c29903813eJake Slack        ConnectorEndPoint connection = (ConnectorEndPoint)endpoint;
13903928aee4356845252ac6b662d5c72c29903813eJake Slack        int lrmit = isLowResources()?_lowResourceMaxIdleTime:_maxIdleTime;
14003928aee4356845252ac6b662d5c72c29903813eJake Slack        connection.setMaxIdleTime(lrmit);
14103928aee4356845252ac6b662d5c72c29903813eJake Slack
14203928aee4356845252ac6b662d5c72c29903813eJake Slack        super.customize(endpoint, request);
14303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14403928aee4356845252ac6b662d5c72c29903813eJake Slack
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
14603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getLocalPort()
14703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _localPort;
14903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15003928aee4356845252ac6b662d5c72c29903813eJake Slack
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStart() throws Exception
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        _connections.clear();
15603928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
15703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15803928aee4356845252ac6b662d5c72c29903813eJake Slack
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStop() throws Exception
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStop();
16403928aee4356845252ac6b662d5c72c29903813eJake Slack        Set<EndPoint> set = new HashSet<EndPoint>();
16503928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized(_connections)
16603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
16703928aee4356845252ac6b662d5c72c29903813eJake Slack            set.addAll(_connections);
16803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
16903928aee4356845252ac6b662d5c72c29903813eJake Slack        for (EndPoint endPoint : set)
17003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17103928aee4356845252ac6b662d5c72c29903813eJake Slack            ConnectorEndPoint connection = (ConnectorEndPoint)endPoint;
17203928aee4356845252ac6b662d5c72c29903813eJake Slack            connection.close();
17303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17503928aee4356845252ac6b662d5c72c29903813eJake Slack
17603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
17703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dump(Appendable out, String indent) throws IOException
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17903928aee4356845252ac6b662d5c72c29903813eJake Slack        super.dump(out, indent);
18003928aee4356845252ac6b662d5c72c29903813eJake Slack        Set<EndPoint> connections = new HashSet<EndPoint>();
18103928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (_connections)
18203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
18303928aee4356845252ac6b662d5c72c29903813eJake Slack            connections.addAll(_connections);
18403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
18503928aee4356845252ac6b662d5c72c29903813eJake Slack        AggregateLifeCycle.dump(out, indent, connections);
18603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18703928aee4356845252ac6b662d5c72c29903813eJake Slack
18803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
19003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected class ConnectorEndPoint extends SocketEndPoint implements Runnable, ConnectedEndPoint
19203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19303928aee4356845252ac6b662d5c72c29903813eJake Slack        volatile Connection _connection;
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        protected final Socket _socket;
19503928aee4356845252ac6b662d5c72c29903813eJake Slack
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        public ConnectorEndPoint(Socket socket) throws IOException
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
19803928aee4356845252ac6b662d5c72c29903813eJake Slack            super(socket,_maxIdleTime);
19903928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection = newConnection(this);
20003928aee4356845252ac6b662d5c72c29903813eJake Slack            _socket=socket;
20103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20203928aee4356845252ac6b662d5c72c29903813eJake Slack
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        public Connection getConnection()
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack            return _connection;
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20703928aee4356845252ac6b662d5c72c29903813eJake Slack
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setConnection(Connection connection)
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_connection!=connection && _connection!=null)
21103928aee4356845252ac6b662d5c72c29903813eJake Slack                connectionUpgraded(_connection,connection);
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            _connection=connection;
21303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
21403928aee4356845252ac6b662d5c72c29903813eJake Slack
21503928aee4356845252ac6b662d5c72c29903813eJake Slack        public void dispatch() throws IOException
21603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (getThreadPool()==null || !getThreadPool().dispatch(this))
21803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("dispatch failed for {}",_connection);
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                close();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22303928aee4356845252ac6b662d5c72c29903813eJake Slack
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
22503928aee4356845252ac6b662d5c72c29903813eJake Slack        public int fill(Buffer buffer) throws IOException
22603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22703928aee4356845252ac6b662d5c72c29903813eJake Slack            int l = super.fill(buffer);
22803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (l<0)
22903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
23003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!isInputShutdown())
23103928aee4356845252ac6b662d5c72c29903813eJake Slack                    shutdownInput();
23203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (isOutputShutdown())
23303928aee4356845252ac6b662d5c72c29903813eJake Slack                    close();
23403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
23503928aee4356845252ac6b662d5c72c29903813eJake Slack            return l;
23603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
23703928aee4356845252ac6b662d5c72c29903813eJake Slack
23803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
23903928aee4356845252ac6b662d5c72c29903813eJake Slack        public void close() throws IOException
24003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
24103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_connection instanceof AbstractHttpConnection)
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                ((AbstractHttpConnection)_connection).getRequest().getAsyncContinuation().cancel();
24303928aee4356845252ac6b662d5c72c29903813eJake Slack            super.close();
24403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
24503928aee4356845252ac6b662d5c72c29903813eJake Slack
24603928aee4356845252ac6b662d5c72c29903813eJake Slack        public void run()
24703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
24803928aee4356845252ac6b662d5c72c29903813eJake Slack            try
24903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
25003928aee4356845252ac6b662d5c72c29903813eJake Slack                connectionOpened(_connection);
25103928aee4356845252ac6b662d5c72c29903813eJake Slack                synchronized(_connections)
25203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
25303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connections.add(this);
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
25503928aee4356845252ac6b662d5c72c29903813eJake Slack
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                while (isStarted() && !isClosed())
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
25803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_connection.isIdle())
25903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (isLowResources())
26103928aee4356845252ac6b662d5c72c29903813eJake Slack                            setMaxIdleTime(getLowResourcesMaxIdleTime());
26203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
26303928aee4356845252ac6b662d5c72c29903813eJake Slack
26403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connection=_connection.handle();
26503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
26603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
26703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (EofException e)
26803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
26903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("EOF", e);
27003928aee4356845252ac6b662d5c72c29903813eJake Slack                try{close();}
27103928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
27203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
27303928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (SocketException e)
27403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
27503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("EOF", e);
27603928aee4356845252ac6b662d5c72c29903813eJake Slack                try{close();}
27703928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
27803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
27903928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (HttpException e)
28003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
28103928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("BAD", e);
28203928aee4356845252ac6b662d5c72c29903813eJake Slack                try{close();}
28303928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
28403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
28503928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Exception e)
28603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("handle failed?",e);
28803928aee4356845252ac6b662d5c72c29903813eJake Slack                try{close();}
28903928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e2){LOG.ignore(e2);}
29003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
29103928aee4356845252ac6b662d5c72c29903813eJake Slack            finally
29203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
29303928aee4356845252ac6b662d5c72c29903813eJake Slack                connectionClosed(_connection);
29403928aee4356845252ac6b662d5c72c29903813eJake Slack                synchronized(_connections)
29503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
29603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _connections.remove(this);
29703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
29803928aee4356845252ac6b662d5c72c29903813eJake Slack
29903928aee4356845252ac6b662d5c72c29903813eJake Slack                // wait for client to close, but if not, close ourselves.
30003928aee4356845252ac6b662d5c72c29903813eJake Slack                try
30103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
30203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!_socket.isClosed())
30303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
30403928aee4356845252ac6b662d5c72c29903813eJake Slack                        long timestamp=System.currentTimeMillis();
30503928aee4356845252ac6b662d5c72c29903813eJake Slack                        int max_idle=getMaxIdleTime();
30603928aee4356845252ac6b662d5c72c29903813eJake Slack
30703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _socket.setSoTimeout(getMaxIdleTime());
30803928aee4356845252ac6b662d5c72c29903813eJake Slack                        int c=0;
30903928aee4356845252ac6b662d5c72c29903813eJake Slack                        do
31003928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                            c = _socket.getInputStream().read();
31203928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                        while (c>=0 && (System.currentTimeMillis()-timestamp)<max_idle);
31403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!_socket.isClosed())
31503928aee4356845252ac6b662d5c72c29903813eJake Slack                            _socket.close();
31603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
31703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e)
31903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
32003928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.ignore(e);
32103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
32203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32503928aee4356845252ac6b662d5c72c29903813eJake Slack}
326