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.http;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.InterruptedIOException;
2303928aee4356845252ac6b662d5c72c29903813eJake Slack
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.BufferCache.CachedBuffer;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.BufferUtil;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffers;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.ByteArrayBuffer;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.StringUtil;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
3403928aee4356845252ac6b662d5c72c29903813eJake Slack
3503928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3603928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3703928aee4356845252ac6b662d5c72c29903813eJake Slack * HttpGenerator. Builds HTTP Messages.
3803928aee4356845252ac6b662d5c72c29903813eJake Slack *
3903928aee4356845252ac6b662d5c72c29903813eJake Slack *
4003928aee4356845252ac6b662d5c72c29903813eJake Slack *
4103928aee4356845252ac6b662d5c72c29903813eJake Slack */
4203928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class HttpGenerator extends AbstractGenerator
4303928aee4356845252ac6b662d5c72c29903813eJake Slack{
4403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(HttpGenerator.class);
4503928aee4356845252ac6b662d5c72c29903813eJake Slack
4603928aee4356845252ac6b662d5c72c29903813eJake Slack    // Build cache of response lines for status
4703928aee4356845252ac6b662d5c72c29903813eJake Slack    private static class Status
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
4903928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer _reason;
5003928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer _schemeCode;
5103928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer _responseLine;
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1];
5403928aee4356845252ac6b662d5c72c29903813eJake Slack    static
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5603928aee4356845252ac6b662d5c72c29903813eJake Slack        int versionLength=HttpVersions.HTTP_1_1_BUFFER.length();
5703928aee4356845252ac6b662d5c72c29903813eJake Slack
5803928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i=0;i<__status.length;i++)
5903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
6003928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpStatus.Code code = HttpStatus.getCode(i);
6103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (code==null)
6203928aee4356845252ac6b662d5c72c29903813eJake Slack                continue;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack            String reason=code.getMessage();
6403928aee4356845252ac6b662d5c72c29903813eJake Slack            byte[] bytes=new byte[versionLength+5+reason.length()+2];
6503928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength);
6603928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+0]=' ';
6703928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+1]=(byte)('0'+i/100);
6803928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+2]=(byte)('0'+(i%100)/10);
6903928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+3]=(byte)('0'+(i%10));
7003928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+4]=' ';
7103928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int j=0;j<reason.length();j++)
7203928aee4356845252ac6b662d5c72c29903813eJake Slack                bytes[versionLength+5+j]=(byte)reason.charAt(j);
7303928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+5+reason.length()]=HttpTokens.CARRIAGE_RETURN;
7403928aee4356845252ac6b662d5c72c29903813eJake Slack            bytes[versionLength+6+reason.length()]=HttpTokens.LINE_FEED;
7503928aee4356845252ac6b662d5c72c29903813eJake Slack
7603928aee4356845252ac6b662d5c72c29903813eJake Slack            __status[i] = new Status();
7703928aee4356845252ac6b662d5c72c29903813eJake Slack            __status[i]._reason=new ByteArrayBuffer(bytes,versionLength+5,bytes.length-versionLength-7,Buffer.IMMUTABLE);
7803928aee4356845252ac6b662d5c72c29903813eJake Slack            __status[i]._schemeCode=new ByteArrayBuffer(bytes,0,versionLength+5,Buffer.IMMUTABLE);
7903928aee4356845252ac6b662d5c72c29903813eJake Slack            __status[i]._responseLine=new ByteArrayBuffer(bytes,0,bytes.length,Buffer.IMMUTABLE);
8003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8203928aee4356845252ac6b662d5c72c29903813eJake Slack
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    public static Buffer getReasonBuffer(int code)
8503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8603928aee4356845252ac6b662d5c72c29903813eJake Slack        Status status = code<__status.length?__status[code]:null;
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (status!=null)
8803928aee4356845252ac6b662d5c72c29903813eJake Slack            return status._reason;
8903928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9103928aee4356845252ac6b662d5c72c29903813eJake Slack
9203928aee4356845252ac6b662d5c72c29903813eJake Slack
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    // common _content
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] LAST_CHUNK =
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'};
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012");
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012");
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012");
9903928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: ");
10003928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] CRLF = StringUtil.getBytes("\015\012");
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012");
10303928aee4356845252ac6b662d5c72c29903813eJake Slack
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    // other statics
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final int CHUNK_SPACE = 12;
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    public static void setServerVersion(String version)
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10903928aee4356845252ac6b662d5c72c29903813eJake Slack        SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012");
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11103928aee4356845252ac6b662d5c72c29903813eJake Slack
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    // data
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _needCRLF = false;
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _needEOC = false;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _bufferChunked = false;
11703928aee4356845252ac6b662d5c72c29903813eJake Slack
11803928aee4356845252ac6b662d5c72c29903813eJake Slack
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
12103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Constructor.
12203928aee4356845252ac6b662d5c72c29903813eJake Slack     *
12303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param buffers buffer pool
12403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param io the end point to use
12503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12603928aee4356845252ac6b662d5c72c29903813eJake Slack    public HttpGenerator(Buffers buffers, EndPoint io)
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12803928aee4356845252ac6b662d5c72c29903813eJake Slack        super(buffers,io);
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13003928aee4356845252ac6b662d5c72c29903813eJake Slack
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void reset()
13403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13703928aee4356845252ac6b662d5c72c29903813eJake Slack            try
13803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
13903928aee4356845252ac6b662d5c72c29903813eJake Slack                _endp.shutdownOutput();
14003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
14103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(IOException e)
14203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
14403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
14503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14603928aee4356845252ac6b662d5c72c29903813eJake Slack        super.reset();
14703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer!=null)
14803928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer.clear();
14903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_header!=null)
15003928aee4356845252ac6b662d5c72c29903813eJake Slack            _header.clear();
15103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_content!=null)
15203928aee4356845252ac6b662d5c72c29903813eJake Slack            _content=null;
15303928aee4356845252ac6b662d5c72c29903813eJake Slack        _bypass = false;
15403928aee4356845252ac6b662d5c72c29903813eJake Slack        _needCRLF = false;
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        _needEOC = false;
15603928aee4356845252ac6b662d5c72c29903813eJake Slack        _bufferChunked=false;
15703928aee4356845252ac6b662d5c72c29903813eJake Slack        _method=null;
15803928aee4356845252ac6b662d5c72c29903813eJake Slack        _uri=null;
15903928aee4356845252ac6b662d5c72c29903813eJake Slack        _noContent=false;
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16103928aee4356845252ac6b662d5c72c29903813eJake Slack
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Add content.
16503928aee4356845252ac6b662d5c72c29903813eJake Slack     *
16603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param content
16703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param last
16803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
16903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IllegalStateException If the request is not expecting any more content,
17003928aee4356845252ac6b662d5c72c29903813eJake Slack     *   or if the buffers are full and cannot be flushed.
17103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException if there is a problem flushing the buffers.
17203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addContent(Buffer content, boolean last) throws IOException
17403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noContent)
17603928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("NO CONTENT");
17703928aee4356845252ac6b662d5c72c29903813eJake Slack
17803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_last || _state==STATE_END)
17903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
18003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn("Ignoring extra content {}",content);
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            content.clear();
18203928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
18303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
18403928aee4356845252ac6b662d5c72c29903813eJake Slack        _last = last;
18503928aee4356845252ac6b662d5c72c29903813eJake Slack
18603928aee4356845252ac6b662d5c72c29903813eJake Slack        // Handle any unfinished business?
18703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_content!=null && _content.length()>0 || _bufferChunked)
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
18903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_endp.isOutputShutdown())
19003928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new EofException();
19103928aee4356845252ac6b662d5c72c29903813eJake Slack            flushBuffer();
19203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_content != null && _content.length()>0)
19303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
19403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_bufferChunked)
19503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
19603928aee4356845252ac6b662d5c72c29903813eJake Slack                    Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length());
19703928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(_content);
19803928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(HttpTokens.CRLF);
19903928aee4356845252ac6b662d5c72c29903813eJake Slack                    BufferUtil.putHexInt(nc, content.length());
20003928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(HttpTokens.CRLF);
20103928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(content);
20203928aee4356845252ac6b662d5c72c29903813eJake Slack                    content=nc;
20303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
20403928aee4356845252ac6b662d5c72c29903813eJake Slack                else
20503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
20603928aee4356845252ac6b662d5c72c29903813eJake Slack                    Buffer nc=_buffers.getBuffer(_content.length()+content.length());
20703928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(_content);
20803928aee4356845252ac6b662d5c72c29903813eJake Slack                    nc.put(content);
20903928aee4356845252ac6b662d5c72c29903813eJake Slack                    content=nc;
21003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
21103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
21203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
21303928aee4356845252ac6b662d5c72c29903813eJake Slack
21403928aee4356845252ac6b662d5c72c29903813eJake Slack        _content = content;
21503928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentWritten += content.length();
21603928aee4356845252ac6b662d5c72c29903813eJake Slack
21703928aee4356845252ac6b662d5c72c29903813eJake Slack        // Handle the _content
21803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_head)
21903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22003928aee4356845252ac6b662d5c72c29903813eJake Slack            content.clear();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack            _content=null;
22203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22303928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024))
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22503928aee4356845252ac6b662d5c72c29903813eJake Slack            _bypass = true;
22603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22703928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (!_bufferChunked)
22803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Yes - so we better check we have a buffer
23003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_buffer == null)
23103928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer = _buffers.getBuffer();
23203928aee4356845252ac6b662d5c72c29903813eJake Slack
23303928aee4356845252ac6b662d5c72c29903813eJake Slack            // Copy _content to buffer;
23403928aee4356845252ac6b662d5c72c29903813eJake Slack            int len=_buffer.put(_content);
23503928aee4356845252ac6b662d5c72c29903813eJake Slack            _content.skip(len);
23603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_content.length() == 0)
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                _content = null;
23803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
23903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24003928aee4356845252ac6b662d5c72c29903813eJake Slack
24103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
24303928aee4356845252ac6b662d5c72c29903813eJake Slack     * send complete response.
24403928aee4356845252ac6b662d5c72c29903813eJake Slack     *
24503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param response
24603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
24703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void sendResponse(Buffer response) throws IOException
24803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
24903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head )
25003928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException();
25103928aee4356845252ac6b662d5c72c29903813eJake Slack
25203928aee4356845252ac6b662d5c72c29903813eJake Slack        _last = true;
25303928aee4356845252ac6b662d5c72c29903813eJake Slack
25403928aee4356845252ac6b662d5c72c29903813eJake Slack        _content = response;
25503928aee4356845252ac6b662d5c72c29903813eJake Slack        _bypass = true;
25603928aee4356845252ac6b662d5c72c29903813eJake Slack        _state = STATE_FLUSHING;
25703928aee4356845252ac6b662d5c72c29903813eJake Slack
25803928aee4356845252ac6b662d5c72c29903813eJake Slack        // TODO this is not exactly right, but should do.
25903928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentLength =_contentWritten = response.length();
26003928aee4356845252ac6b662d5c72c29903813eJake Slack
26103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26203928aee4356845252ac6b662d5c72c29903813eJake Slack
26303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Prepare buffer for unchecked writes.
26503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Prepare the generator buffer to receive unchecked writes
26603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the available space in the buffer.
26703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException
26803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
26903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
27003928aee4356845252ac6b662d5c72c29903813eJake Slack    public int prepareUncheckedAddContent() throws IOException
27103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noContent)
27303928aee4356845252ac6b662d5c72c29903813eJake Slack            return -1;
27403928aee4356845252ac6b662d5c72c29903813eJake Slack
27503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_last || _state==STATE_END)
27603928aee4356845252ac6b662d5c72c29903813eJake Slack            return -1;
27703928aee4356845252ac6b662d5c72c29903813eJake Slack
27803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Handle any unfinished business?
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer content = _content;
28003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (content != null && content.length()>0 || _bufferChunked)
28103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28203928aee4356845252ac6b662d5c72c29903813eJake Slack            flushBuffer();
28303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (content != null && content.length()>0 || _bufferChunked)
28403928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException("FULL");
28503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28603928aee4356845252ac6b662d5c72c29903813eJake Slack
28703928aee4356845252ac6b662d5c72c29903813eJake Slack        // we better check we have a buffer
28803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer == null)
28903928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer = _buffers.getBuffer();
29003928aee4356845252ac6b662d5c72c29903813eJake Slack
29103928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentWritten-=_buffer.length();
29203928aee4356845252ac6b662d5c72c29903813eJake Slack
29303928aee4356845252ac6b662d5c72c29903813eJake Slack        // Handle the _content
29403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_head)
29503928aee4356845252ac6b662d5c72c29903813eJake Slack            return Integer.MAX_VALUE;
29603928aee4356845252ac6b662d5c72c29903813eJake Slack
29703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0);
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29903928aee4356845252ac6b662d5c72c29903813eJake Slack
30003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
30203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isBufferFull()
30303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        // Should we flush the buffers?
30503928aee4356845252ac6b662d5c72c29903813eJake Slack        return super.isBufferFull() || _bufferChunked || _bypass  || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE);
30603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30703928aee4356845252ac6b662d5c72c29903813eJake Slack
30803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void send1xx(int code) throws IOException
31003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state != STATE_HEADER)
31203928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
31303928aee4356845252ac6b662d5c72c29903813eJake Slack
31403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (code<100||code>199)
31503928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException("!1xx");
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        Status status=__status[code];
31703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (status==null)
31803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException(code+"?");
31903928aee4356845252ac6b662d5c72c29903813eJake Slack
32003928aee4356845252ac6b662d5c72c29903813eJake Slack        // get a header buffer
32103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_header == null)
32203928aee4356845252ac6b662d5c72c29903813eJake Slack            _header = _buffers.getHeader();
32303928aee4356845252ac6b662d5c72c29903813eJake Slack
32403928aee4356845252ac6b662d5c72c29903813eJake Slack        _header.put(status._responseLine);
32503928aee4356845252ac6b662d5c72c29903813eJake Slack        _header.put(HttpTokens.CRLF);
32603928aee4356845252ac6b662d5c72c29903813eJake Slack
32703928aee4356845252ac6b662d5c72c29903813eJake Slack        try
32803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
32903928aee4356845252ac6b662d5c72c29903813eJake Slack            // nasty semi busy flush!
33003928aee4356845252ac6b662d5c72c29903813eJake Slack            while(_header.length()>0)
33103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
33203928aee4356845252ac6b662d5c72c29903813eJake Slack                int len = _endp.flush(_header);
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (len<0)
33403928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new EofException();
33503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (len==0)
33603928aee4356845252ac6b662d5c72c29903813eJake Slack                    Thread.sleep(100);
33703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(InterruptedException e)
34003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug(e);
34203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new InterruptedIOException(e.toString());
34303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34503928aee4356845252ac6b662d5c72c29903813eJake Slack
34603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
34703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
34803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isRequest()
34903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _method!=null;
35103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35203928aee4356845252ac6b662d5c72c29903813eJake Slack
35303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35403928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
35503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isResponse()
35603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _method==null;
35803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35903928aee4356845252ac6b662d5c72c29903813eJake Slack
36003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
36303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state != STATE_HEADER)
36503928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
36603928aee4356845252ac6b662d5c72c29903813eJake Slack
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        // handle a reset
36803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (isResponse() && _status==0)
36903928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new EofException();
37003928aee4356845252ac6b662d5c72c29903813eJake Slack
37103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_last && !allContentAdded)
37203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("last?");
37303928aee4356845252ac6b662d5c72c29903813eJake Slack        _last = _last | allContentAdded;
37403928aee4356845252ac6b662d5c72c29903813eJake Slack
37503928aee4356845252ac6b662d5c72c29903813eJake Slack        // get a header buffer
37603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_header == null)
37703928aee4356845252ac6b662d5c72c29903813eJake Slack            _header = _buffers.getHeader();
37803928aee4356845252ac6b662d5c72c29903813eJake Slack
37903928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean has_server = false;
38003928aee4356845252ac6b662d5c72c29903813eJake Slack
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        try
38203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isRequest())
38403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38503928aee4356845252ac6b662d5c72c29903813eJake Slack                _persistent=true;
38603928aee4356845252ac6b662d5c72c29903813eJake Slack
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_version == HttpVersions.HTTP_0_9_ORDINAL)
38803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
38903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _contentLength = HttpTokens.NO_CONTENT;
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(_method);
39103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put((byte)' ');
39203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(_uri.getBytes("UTF-8")); // TODO check
39303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(HttpTokens.CRLF);
39403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state = STATE_FLUSHING;
39503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _noContent=true;
39603928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
39703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
39803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
39903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
40003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(_method);
40103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put((byte)' ');
40203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(_uri.getBytes("UTF-8")); // TODO check
40303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put((byte)' ');
40403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER);
40503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(HttpTokens.CRLF);
40603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
40703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
40803928aee4356845252ac6b662d5c72c29903813eJake Slack            else
40903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
41003928aee4356845252ac6b662d5c72c29903813eJake Slack                // Responses
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_version == HttpVersions.HTTP_0_9_ORDINAL)
41203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
41303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _persistent = false;
41403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _contentLength = HttpTokens.EOF_CONTENT;
41503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state = STATE_CONTENT;
41603928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
41703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
41803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
41903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
42003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_persistent==null)
42103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL);
42203928aee4356845252ac6b662d5c72c29903813eJake Slack
42303928aee4356845252ac6b662d5c72c29903813eJake Slack                    // add response line
42403928aee4356845252ac6b662d5c72c29903813eJake Slack                    Status status = _status<__status.length?__status[_status]:null;
42503928aee4356845252ac6b662d5c72c29903813eJake Slack
42603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (status==null)
42703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
42803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(HttpVersions.HTTP_1_1_BUFFER);
42903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte) ' ');
43003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte) ('0' + _status / 100));
43103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte) ('0' + (_status % 100) / 10));
43203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte) ('0' + (_status % 10)));
43303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte) ' ');
43403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_reason==null)
43503928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
43603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put((byte) ('0' + _status / 100));
43703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put((byte) ('0' + (_status % 100) / 10));
43803928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put((byte) ('0' + (_status % 10)));
43903928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
44003928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
44103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(_reason);
44203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(HttpTokens.CRLF);
44303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
44403928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
44503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
44603928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_reason==null)
44703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(status._responseLine);
44803928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
44903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
45003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(status._schemeCode);
45103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(_reason);
45203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.CRLF);
45303928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
45403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
45503928aee4356845252ac6b662d5c72c29903813eJake Slack
45603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_status<200 && _status>=100 )
45703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
45803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _noContent=true;
45903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _content=null;
46003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer!=null)
46103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.clear();
46203928aee4356845252ac6b662d5c72c29903813eJake Slack                        // end the header.
46303928aee4356845252ac6b662d5c72c29903813eJake Slack
46403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_status!=101 )
46503928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
46603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.CRLF);
46703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state = STATE_CONTENT;
46803928aee4356845252ac6b662d5c72c29903813eJake Slack                            return;
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
47103928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if (_status==204 || _status==304)
47203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
47303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _noContent=true;
47403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _content=null;
47503928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer!=null)
47603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.clear();
47703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
47803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
47903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48003928aee4356845252ac6b662d5c72c29903813eJake Slack
48103928aee4356845252ac6b662d5c72c29903813eJake Slack            // Add headers
48203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_status>=200 && _date!=null)
48303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48403928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put(HttpHeaders.DATE_BUFFER);
48503928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put((byte)':');
48603928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put((byte)' ');
48703928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put(_date);
48803928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put(CRLF);
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
49003928aee4356845252ac6b662d5c72c29903813eJake Slack
49103928aee4356845252ac6b662d5c72c29903813eJake Slack            // key field values
49203928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpFields.Field content_length = null;
49303928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpFields.Field transfer_encoding = null;
49403928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean keep_alive = false;
49503928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean close=false;
49603928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean content_type=false;
49703928aee4356845252ac6b662d5c72c29903813eJake Slack            StringBuilder connection = null;
49803928aee4356845252ac6b662d5c72c29903813eJake Slack
49903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (fields != null)
50003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
50103928aee4356845252ac6b662d5c72c29903813eJake Slack                int s=fields.size();
50203928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int f=0;f<s;f++)
50303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
50403928aee4356845252ac6b662d5c72c29903813eJake Slack                    HttpFields.Field field = fields.getField(f);
50503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (field==null)
50603928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
50703928aee4356845252ac6b662d5c72c29903813eJake Slack
50803928aee4356845252ac6b662d5c72c29903813eJake Slack                    switch (field.getNameOrdinal())
50903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
51003928aee4356845252ac6b662d5c72c29903813eJake Slack                        case HttpHeaders.CONTENT_LENGTH_ORDINAL:
51103928aee4356845252ac6b662d5c72c29903813eJake Slack                            content_length = field;
51203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _contentLength = field.getLongValue();
51303928aee4356845252ac6b662d5c72c29903813eJake Slack
51403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_contentLength < _contentWritten || _last && _contentLength != _contentWritten)
51503928aee4356845252ac6b662d5c72c29903813eJake Slack                                content_length = null;
51603928aee4356845252ac6b662d5c72c29903813eJake Slack
51703928aee4356845252ac6b662d5c72c29903813eJake Slack                            // write the field to the header buffer
51803928aee4356845252ac6b662d5c72c29903813eJake Slack                            field.putTo(_header);
51903928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
52003928aee4356845252ac6b662d5c72c29903813eJake Slack
52103928aee4356845252ac6b662d5c72c29903813eJake Slack                        case HttpHeaders.CONTENT_TYPE_ORDINAL:
52203928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
52303928aee4356845252ac6b662d5c72c29903813eJake Slack
52403928aee4356845252ac6b662d5c72c29903813eJake Slack                            // write the field to the header buffer
52503928aee4356845252ac6b662d5c72c29903813eJake Slack                            content_type=true;
52603928aee4356845252ac6b662d5c72c29903813eJake Slack                            field.putTo(_header);
52703928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
52803928aee4356845252ac6b662d5c72c29903813eJake Slack
52903928aee4356845252ac6b662d5c72c29903813eJake Slack                        case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
53003928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_version == HttpVersions.HTTP_1_1_ORDINAL)
53103928aee4356845252ac6b662d5c72c29903813eJake Slack                                transfer_encoding = field;
53203928aee4356845252ac6b662d5c72c29903813eJake Slack                            // Do NOT add yet!
53303928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
53403928aee4356845252ac6b662d5c72c29903813eJake Slack
53503928aee4356845252ac6b662d5c72c29903813eJake Slack                        case HttpHeaders.CONNECTION_ORDINAL:
53603928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (isRequest())
53703928aee4356845252ac6b662d5c72c29903813eJake Slack                                field.putTo(_header);
53803928aee4356845252ac6b662d5c72c29903813eJake Slack
53903928aee4356845252ac6b662d5c72c29903813eJake Slack                            int connection_value = field.getValueOrdinal();
54003928aee4356845252ac6b662d5c72c29903813eJake Slack                            switch (connection_value)
54103928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
54203928aee4356845252ac6b662d5c72c29903813eJake Slack                                case -1:
54303928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
54403928aee4356845252ac6b662d5c72c29903813eJake Slack                                    String[] values = field.getValue().split(",");
54503928aee4356845252ac6b662d5c72c29903813eJake Slack                                    for  (int i=0;values!=null && i<values.length;i++)
54603928aee4356845252ac6b662d5c72c29903813eJake Slack                                    {
54703928aee4356845252ac6b662d5c72c29903813eJake Slack                                        CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
54803928aee4356845252ac6b662d5c72c29903813eJake Slack
54903928aee4356845252ac6b662d5c72c29903813eJake Slack                                        if (cb!=null)
55003928aee4356845252ac6b662d5c72c29903813eJake Slack                                        {
55103928aee4356845252ac6b662d5c72c29903813eJake Slack                                            switch(cb.getOrdinal())
55203928aee4356845252ac6b662d5c72c29903813eJake Slack                                            {
55303928aee4356845252ac6b662d5c72c29903813eJake Slack                                                case HttpHeaderValues.CLOSE_ORDINAL:
55403928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    close=true;
55503928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    if (isResponse())
55603928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        _persistent=false;
55703928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    keep_alive=false;
55803928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
55903928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        _contentLength = HttpTokens.EOF_CONTENT;
56003928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    break;
56103928aee4356845252ac6b662d5c72c29903813eJake Slack
56203928aee4356845252ac6b662d5c72c29903813eJake Slack                                                case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
56303928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    if (_version == HttpVersions.HTTP_1_0_ORDINAL)
56403928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    {
56503928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        keep_alive = true;
56603928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        if (isResponse())
56703928aee4356845252ac6b662d5c72c29903813eJake Slack                                                            _persistent = true;
56803928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    }
56903928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    break;
57003928aee4356845252ac6b662d5c72c29903813eJake Slack
57103928aee4356845252ac6b662d5c72c29903813eJake Slack                                                default:
57203928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    if (connection==null)
57303928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        connection=new StringBuilder();
57403928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    else
57503928aee4356845252ac6b662d5c72c29903813eJake Slack                                                        connection.append(',');
57603928aee4356845252ac6b662d5c72c29903813eJake Slack                                                    connection.append(values[i]);
57703928aee4356845252ac6b662d5c72c29903813eJake Slack                                            }
57803928aee4356845252ac6b662d5c72c29903813eJake Slack                                        }
57903928aee4356845252ac6b662d5c72c29903813eJake Slack                                        else
58003928aee4356845252ac6b662d5c72c29903813eJake Slack                                        {
58103928aee4356845252ac6b662d5c72c29903813eJake Slack                                            if (connection==null)
58203928aee4356845252ac6b662d5c72c29903813eJake Slack                                                connection=new StringBuilder();
58303928aee4356845252ac6b662d5c72c29903813eJake Slack                                            else
58403928aee4356845252ac6b662d5c72c29903813eJake Slack                                                connection.append(',');
58503928aee4356845252ac6b662d5c72c29903813eJake Slack                                            connection.append(values[i]);
58603928aee4356845252ac6b662d5c72c29903813eJake Slack                                        }
58703928aee4356845252ac6b662d5c72c29903813eJake Slack                                    }
58803928aee4356845252ac6b662d5c72c29903813eJake Slack
58903928aee4356845252ac6b662d5c72c29903813eJake Slack                                    break;
59003928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
59103928aee4356845252ac6b662d5c72c29903813eJake Slack                                case HttpHeaderValues.UPGRADE_ORDINAL:
59203928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
59303928aee4356845252ac6b662d5c72c29903813eJake Slack                                    // special case for websocket connection ordering
59403928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (isResponse())
59503928aee4356845252ac6b662d5c72c29903813eJake Slack                                    {
59603928aee4356845252ac6b662d5c72c29903813eJake Slack                                        field.putTo(_header);
59703928aee4356845252ac6b662d5c72c29903813eJake Slack                                        continue;
59803928aee4356845252ac6b662d5c72c29903813eJake Slack                                    }
59903928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
60003928aee4356845252ac6b662d5c72c29903813eJake Slack                                case HttpHeaderValues.CLOSE_ORDINAL:
60103928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
60203928aee4356845252ac6b662d5c72c29903813eJake Slack                                    close=true;
60303928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (isResponse())
60403928aee4356845252ac6b662d5c72c29903813eJake Slack                                        _persistent=false;
60503928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
60603928aee4356845252ac6b662d5c72c29903813eJake Slack                                        _contentLength = HttpTokens.EOF_CONTENT;
60703928aee4356845252ac6b662d5c72c29903813eJake Slack                                    break;
60803928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
60903928aee4356845252ac6b662d5c72c29903813eJake Slack                                case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
61003928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
61103928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (_version == HttpVersions.HTTP_1_0_ORDINAL)
61203928aee4356845252ac6b662d5c72c29903813eJake Slack                                    {
61303928aee4356845252ac6b662d5c72c29903813eJake Slack                                        keep_alive = true;
61403928aee4356845252ac6b662d5c72c29903813eJake Slack                                        if (isResponse())
61503928aee4356845252ac6b662d5c72c29903813eJake Slack                                            _persistent=true;
61603928aee4356845252ac6b662d5c72c29903813eJake Slack                                    }
61703928aee4356845252ac6b662d5c72c29903813eJake Slack                                    break;
61803928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
61903928aee4356845252ac6b662d5c72c29903813eJake Slack                                default:
62003928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
62103928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (connection==null)
62203928aee4356845252ac6b662d5c72c29903813eJake Slack                                        connection=new StringBuilder();
62303928aee4356845252ac6b662d5c72c29903813eJake Slack                                    else
62403928aee4356845252ac6b662d5c72c29903813eJake Slack                                        connection.append(',');
62503928aee4356845252ac6b662d5c72c29903813eJake Slack                                    connection.append(field.getValue());
62603928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
62703928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
62803928aee4356845252ac6b662d5c72c29903813eJake Slack
62903928aee4356845252ac6b662d5c72c29903813eJake Slack                            // Do NOT add yet!
63003928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
63103928aee4356845252ac6b662d5c72c29903813eJake Slack
63203928aee4356845252ac6b662d5c72c29903813eJake Slack                        case HttpHeaders.SERVER_ORDINAL:
63303928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (getSendServerVersion())
63403928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
63503928aee4356845252ac6b662d5c72c29903813eJake Slack                                has_server=true;
63603928aee4356845252ac6b662d5c72c29903813eJake Slack                                field.putTo(_header);
63703928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
63803928aee4356845252ac6b662d5c72c29903813eJake Slack                            break;
63903928aee4356845252ac6b662d5c72c29903813eJake Slack
64003928aee4356845252ac6b662d5c72c29903813eJake Slack                        default:
64103928aee4356845252ac6b662d5c72c29903813eJake Slack                            // write the field to the header buffer
64203928aee4356845252ac6b662d5c72c29903813eJake Slack                            field.putTo(_header);
64303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
64403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
64503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
64603928aee4356845252ac6b662d5c72c29903813eJake Slack
64703928aee4356845252ac6b662d5c72c29903813eJake Slack            // Calculate how to end _content and connection, _content length and transfer encoding
64803928aee4356845252ac6b662d5c72c29903813eJake Slack            // settings.
64903928aee4356845252ac6b662d5c72c29903813eJake Slack            // From RFC 2616 4.4:
65003928aee4356845252ac6b662d5c72c29903813eJake Slack            // 1. No body for 1xx, 204, 304 & HEAD response
65103928aee4356845252ac6b662d5c72c29903813eJake Slack            // 2. Force _content-length?
65203928aee4356845252ac6b662d5c72c29903813eJake Slack            // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk
65303928aee4356845252ac6b662d5c72c29903813eJake Slack            // 4. Content-Length
65403928aee4356845252ac6b662d5c72c29903813eJake Slack            // 5. multipart/byteranges
65503928aee4356845252ac6b662d5c72c29903813eJake Slack            // 6. close
65603928aee4356845252ac6b662d5c72c29903813eJake Slack            switch ((int) _contentLength)
65703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
65803928aee4356845252ac6b662d5c72c29903813eJake Slack                case HttpTokens.UNKNOWN_CONTENT:
65903928aee4356845252ac6b662d5c72c29903813eJake Slack                    // It may be that we have no _content, or perhaps _content just has not been
66003928aee4356845252ac6b662d5c72c29903813eJake Slack                    // written yet?
66103928aee4356845252ac6b662d5c72c29903813eJake Slack
66203928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Response known not to have a body
66303928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_contentWritten == 0 && isResponse() && (_status < 200 || _status == 204 || _status == 304))
66403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _contentLength = HttpTokens.NO_CONTENT;
66503928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if (_last)
66603928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
66703928aee4356845252ac6b662d5c72c29903813eJake Slack                        // we have seen all the _content there is
66803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _contentLength = _contentWritten;
66903928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent)
67003928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
67103928aee4356845252ac6b662d5c72c29903813eJake Slack                            // known length but not actually set.
67203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
67303928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.COLON);
67403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put((byte) ' ');
67503928aee4356845252ac6b662d5c72c29903813eJake Slack                            BufferUtil.putDecLong(_header, _contentLength);
67603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.CRLF);
67703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
67803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
67903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
68003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
68103928aee4356845252ac6b662d5c72c29903813eJake Slack                        // No idea, so we must assume that a body is coming
68203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT;
68303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT)
68403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
68503928aee4356845252ac6b662d5c72c29903813eJake Slack                            _contentLength=HttpTokens.NO_CONTENT;
68603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _noContent=true;
68703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
68803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
68903928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
69003928aee4356845252ac6b662d5c72c29903813eJake Slack
69103928aee4356845252ac6b662d5c72c29903813eJake Slack                case HttpTokens.NO_CONTENT:
69203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304)
69303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(CONTENT_LENGTH_0);
69403928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
69503928aee4356845252ac6b662d5c72c29903813eJake Slack
69603928aee4356845252ac6b662d5c72c29903813eJake Slack                case HttpTokens.EOF_CONTENT:
69703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _persistent = isRequest();
69803928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
69903928aee4356845252ac6b662d5c72c29903813eJake Slack
70003928aee4356845252ac6b662d5c72c29903813eJake Slack                case HttpTokens.CHUNKED_CONTENT:
70103928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
70203928aee4356845252ac6b662d5c72c29903813eJake Slack
70303928aee4356845252ac6b662d5c72c29903813eJake Slack                default:
70403928aee4356845252ac6b662d5c72c29903813eJake Slack                    // TODO - maybe allow forced chunking by setting te ???
70503928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
70603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
70703928aee4356845252ac6b662d5c72c29903813eJake Slack
70803928aee4356845252ac6b662d5c72c29903813eJake Slack            // Add transfer_encoding if needed
70903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
71003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
71103928aee4356845252ac6b662d5c72c29903813eJake Slack                // try to use user supplied encoding as it may have other values.
71203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal())
71303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
71403928aee4356845252ac6b662d5c72c29903813eJake Slack                    String c = transfer_encoding.getValue();
71503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (c.endsWith(HttpHeaderValues.CHUNKED))
71603928aee4356845252ac6b662d5c72c29903813eJake Slack                        transfer_encoding.putTo(_header);
71703928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
71803928aee4356845252ac6b662d5c72c29903813eJake Slack                        throw new IllegalArgumentException("BAD TE");
71903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
72003928aee4356845252ac6b662d5c72c29903813eJake Slack                else
72103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(TRANSFER_ENCODING_CHUNKED);
72203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
72303928aee4356845252ac6b662d5c72c29903813eJake Slack
72403928aee4356845252ac6b662d5c72c29903813eJake Slack            // Handle connection if need be
72503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contentLength==HttpTokens.EOF_CONTENT)
72603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
72703928aee4356845252ac6b662d5c72c29903813eJake Slack                keep_alive=false;
72803928aee4356845252ac6b662d5c72c29903813eJake Slack                _persistent=false;
72903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
73003928aee4356845252ac6b662d5c72c29903813eJake Slack
73103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (isResponse())
73203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
73303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL))
73403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
73503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(CONNECTION_CLOSE);
73603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (connection!=null)
73703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
73803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.setPutIndex(_header.putIndex()-2);
73903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte)',');
74003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(connection.toString().getBytes());
74103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(CRLF);
74203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
74303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
74403928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (keep_alive)
74503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
74603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(CONNECTION_KEEP_ALIVE);
74703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (connection!=null)
74803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
74903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.setPutIndex(_header.putIndex()-2);
75003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put((byte)',');
75103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(connection.toString().getBytes());
75203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(CRLF);
75303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
75403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
75503928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (connection!=null)
75603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
75703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(CONNECTION_);
75803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(connection.toString().getBytes());
75903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(CRLF);
76003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
76103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
76203928aee4356845252ac6b662d5c72c29903813eJake Slack
76303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!has_server && _status>199 && getSendServerVersion())
76403928aee4356845252ac6b662d5c72c29903813eJake Slack                _header.put(SERVER);
76503928aee4356845252ac6b662d5c72c29903813eJake Slack
76603928aee4356845252ac6b662d5c72c29903813eJake Slack            // end the header.
76703928aee4356845252ac6b662d5c72c29903813eJake Slack            _header.put(HttpTokens.CRLF);
76803928aee4356845252ac6b662d5c72c29903813eJake Slack            _state = STATE_CONTENT;
76903928aee4356845252ac6b662d5c72c29903813eJake Slack
77003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
77103928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(ArrayIndexOutOfBoundsException e)
77203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
77303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new RuntimeException("Header>"+_header.capacity(),e);
77403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
77503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
77603928aee4356845252ac6b662d5c72c29903813eJake Slack
77703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
77803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
77903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Complete the message.
78003928aee4356845252ac6b662d5c72c29903813eJake Slack     *
78103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException
78203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
78303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
78403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void complete() throws IOException
78503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
78603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state == STATE_END)
78703928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
78803928aee4356845252ac6b662d5c72c29903813eJake Slack
78903928aee4356845252ac6b662d5c72c29903813eJake Slack        super.complete();
79003928aee4356845252ac6b662d5c72c29903813eJake Slack
79103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state < STATE_FLUSHING)
79203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
79303928aee4356845252ac6b662d5c72c29903813eJake Slack            _state = STATE_FLUSHING;
79403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
79503928aee4356845252ac6b662d5c72c29903813eJake Slack                _needEOC = true;
79603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
79703928aee4356845252ac6b662d5c72c29903813eJake Slack
79803928aee4356845252ac6b662d5c72c29903813eJake Slack        flushBuffer();
79903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
80003928aee4356845252ac6b662d5c72c29903813eJake Slack
80103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
80203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
80303928aee4356845252ac6b662d5c72c29903813eJake Slack    public int flushBuffer() throws IOException
80403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
80503928aee4356845252ac6b662d5c72c29903813eJake Slack        try
80603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
80703928aee4356845252ac6b662d5c72c29903813eJake Slack
80803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_state == STATE_HEADER)
80903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException("State==HEADER");
81003928aee4356845252ac6b662d5c72c29903813eJake Slack
81103928aee4356845252ac6b662d5c72c29903813eJake Slack            prepareBuffers();
81203928aee4356845252ac6b662d5c72c29903813eJake Slack
81303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_endp == null)
81403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
81503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_needCRLF && _buffer!=null)
81603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _buffer.put(HttpTokens.CRLF);
81703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_needEOC && _buffer!=null && !_head)
81803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _buffer.put(LAST_CHUNK);
81903928aee4356845252ac6b662d5c72c29903813eJake Slack                _needCRLF=false;
82003928aee4356845252ac6b662d5c72c29903813eJake Slack                _needEOC=false;
82103928aee4356845252ac6b662d5c72c29903813eJake Slack                return 0;
82203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
82303928aee4356845252ac6b662d5c72c29903813eJake Slack
82403928aee4356845252ac6b662d5c72c29903813eJake Slack            int total= 0;
82503928aee4356845252ac6b662d5c72c29903813eJake Slack
82603928aee4356845252ac6b662d5c72c29903813eJake Slack            int len = -1;
82703928aee4356845252ac6b662d5c72c29903813eJake Slack            int to_flush = flushMask();
82803928aee4356845252ac6b662d5c72c29903813eJake Slack            int last_flush;
82903928aee4356845252ac6b662d5c72c29903813eJake Slack
83003928aee4356845252ac6b662d5c72c29903813eJake Slack            do
83103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
83203928aee4356845252ac6b662d5c72c29903813eJake Slack                last_flush=to_flush;
83303928aee4356845252ac6b662d5c72c29903813eJake Slack                switch (to_flush)
83403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
83503928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 7:
83603928aee4356845252ac6b662d5c72c29903813eJake Slack                        throw new IllegalStateException(); // should never happen!
83703928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 6:
83803928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_header, _buffer, null);
83903928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
84003928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 5:
84103928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_header, _content, null);
84203928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
84303928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 4:
84403928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_header);
84503928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
84603928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 3:
84703928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_buffer, _content, null);
84803928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
84903928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 2:
85003928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_buffer);
85103928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
85203928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 1:
85303928aee4356845252ac6b662d5c72c29903813eJake Slack                        len = _endp.flush(_content);
85403928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
85503928aee4356845252ac6b662d5c72c29903813eJake Slack                    case 0:
85603928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
85703928aee4356845252ac6b662d5c72c29903813eJake Slack                        len=0;
85803928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Nothing more we can write now.
85903928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_header != null)
86003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.clear();
86103928aee4356845252ac6b662d5c72c29903813eJake Slack
86203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bypass = false;
86303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bufferChunked = false;
86403928aee4356845252ac6b662d5c72c29903813eJake Slack
86503928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer != null)
86603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
86703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.clear();
86803928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
86903928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
87003928aee4356845252ac6b662d5c72c29903813eJake Slack                                // reserve some space for the chunk header
87103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer.setPutIndex(CHUNK_SPACE);
87203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer.setGetIndex(CHUNK_SPACE);
87303928aee4356845252ac6b662d5c72c29903813eJake Slack
87403928aee4356845252ac6b662d5c72c29903813eJake Slack                                // Special case handling for small left over buffer from
87503928aee4356845252ac6b662d5c72c29903813eJake Slack                                // an addContent that caused a buffer flush.
87603928aee4356845252ac6b662d5c72c29903813eJake Slack                                if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
87703928aee4356845252ac6b662d5c72c29903813eJake Slack                                {
87803928aee4356845252ac6b662d5c72c29903813eJake Slack                                    _buffer.put(_content);
87903928aee4356845252ac6b662d5c72c29903813eJake Slack                                    _content.clear();
88003928aee4356845252ac6b662d5c72c29903813eJake Slack                                    _content=null;
88103928aee4356845252ac6b662d5c72c29903813eJake Slack                                }
88203928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
88303928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
88403928aee4356845252ac6b662d5c72c29903813eJake Slack
88503928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Are we completely finished for now?
88603928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
88703928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
88803928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_state == STATE_FLUSHING)
88903928aee4356845252ac6b662d5c72c29903813eJake Slack                                _state = STATE_END;
89003928aee4356845252ac6b662d5c72c29903813eJake Slack
89103928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
89203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _endp.shutdownOutput();
89303928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
89403928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
89503928aee4356845252ac6b662d5c72c29903813eJake Slack                            // Try to prepare more to write.
89603928aee4356845252ac6b662d5c72c29903813eJake Slack                            prepareBuffers();
89703928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
89803928aee4356845252ac6b662d5c72c29903813eJake Slack
89903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
90003928aee4356845252ac6b662d5c72c29903813eJake Slack
90103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (len > 0)
90203928aee4356845252ac6b662d5c72c29903813eJake Slack                    total+=len;
90303928aee4356845252ac6b662d5c72c29903813eJake Slack
90403928aee4356845252ac6b662d5c72c29903813eJake Slack                to_flush = flushMask();
90503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
90603928aee4356845252ac6b662d5c72c29903813eJake Slack            // loop while progress is being made (OR we have prepared some buffers that might make progress)
90703928aee4356845252ac6b662d5c72c29903813eJake Slack            while (len>0 || (to_flush!=0 && last_flush==0));
90803928aee4356845252ac6b662d5c72c29903813eJake Slack
90903928aee4356845252ac6b662d5c72c29903813eJake Slack            return total;
91003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
91103928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (IOException e)
91203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
91303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
91403928aee4356845252ac6b662d5c72c29903813eJake Slack            throw (e instanceof EofException) ? e:new EofException(e);
91503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
91603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
91703928aee4356845252ac6b662d5c72c29903813eJake Slack
91803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
91903928aee4356845252ac6b662d5c72c29903813eJake Slack    private int flushMask()
92003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
92103928aee4356845252ac6b662d5c72c29903813eJake Slack        return  ((_header != null && _header.length() > 0)?4:0)
92203928aee4356845252ac6b662d5c72c29903813eJake Slack        | ((_buffer != null && _buffer.length() > 0)?2:0)
92303928aee4356845252ac6b662d5c72c29903813eJake Slack        | ((_bypass && _content != null && _content.length() > 0)?1:0);
92403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
92503928aee4356845252ac6b662d5c72c29903813eJake Slack
92603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
92703928aee4356845252ac6b662d5c72c29903813eJake Slack    private void prepareBuffers()
92803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
92903928aee4356845252ac6b662d5c72c29903813eJake Slack        // if we are not flushing an existing chunk
93003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_bufferChunked)
93103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
93203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Refill buffer if possible
93303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0)
93403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
93503928aee4356845252ac6b662d5c72c29903813eJake Slack                int len = _buffer.put(_content);
93603928aee4356845252ac6b662d5c72c29903813eJake Slack                _content.skip(len);
93703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_content.length() == 0)
93803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _content = null;
93903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
94003928aee4356845252ac6b662d5c72c29903813eJake Slack
94103928aee4356845252ac6b662d5c72c29903813eJake Slack            // Chunk buffer if need be
94203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
94303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
94403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null)
94503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
94603928aee4356845252ac6b662d5c72c29903813eJake Slack                    // this is a bypass write
94703928aee4356845252ac6b662d5c72c29903813eJake Slack                    int size = _content.length();
94803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _bufferChunked = true;
94903928aee4356845252ac6b662d5c72c29903813eJake Slack
95003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_header == null)
95103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header = _buffers.getHeader();
95203928aee4356845252ac6b662d5c72c29903813eJake Slack
95303928aee4356845252ac6b662d5c72c29903813eJake Slack                    // if we need CRLF add this to header
95403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_needCRLF)
95503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
95603928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_header.length() > 0) throw new IllegalStateException("EOC");
95703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header.put(HttpTokens.CRLF);
95803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _needCRLF = false;
95903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
96003928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Add the chunk size to the header
96103928aee4356845252ac6b662d5c72c29903813eJake Slack                    BufferUtil.putHexInt(_header, size);
96203928aee4356845252ac6b662d5c72c29903813eJake Slack                    _header.put(HttpTokens.CRLF);
96303928aee4356845252ac6b662d5c72c29903813eJake Slack
96403928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Need a CRLF after the content
96503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _needCRLF=true;
96603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
96703928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (_buffer!=null)
96803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
96903928aee4356845252ac6b662d5c72c29903813eJake Slack                    int size = _buffer.length();
97003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (size > 0)
97103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
97203928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Prepare a chunk!
97303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bufferChunked = true;
97403928aee4356845252ac6b662d5c72c29903813eJake Slack
97503928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Did we leave space at the start of the buffer.
97603928aee4356845252ac6b662d5c72c29903813eJake Slack                        //noinspection ConstantConditions
97703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer.getIndex() == CHUNK_SPACE)
97803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
97903928aee4356845252ac6b662d5c72c29903813eJake Slack                            // Oh yes, goodie! let's use it then!
98003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
98103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.setGetIndex(_buffer.getIndex() - 2);
98203928aee4356845252ac6b662d5c72c29903813eJake Slack                            BufferUtil.prependHexInt(_buffer, size);
98303928aee4356845252ac6b662d5c72c29903813eJake Slack
98403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_needCRLF)
98503928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
98603928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
98703928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer.setGetIndex(_buffer.getIndex() - 2);
98803928aee4356845252ac6b662d5c72c29903813eJake Slack                                _needCRLF = false;
98903928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
99003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
99103928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
99203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
99303928aee4356845252ac6b662d5c72c29903813eJake Slack                            // No space so lets use a header buffer.
99403928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_header == null)
99503928aee4356845252ac6b662d5c72c29903813eJake Slack                                _header = _buffers.getHeader();
99603928aee4356845252ac6b662d5c72c29903813eJake Slack
99703928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_needCRLF)
99803928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
99903928aee4356845252ac6b662d5c72c29903813eJake Slack                                if (_header.length() > 0) throw new IllegalStateException("EOC");
100003928aee4356845252ac6b662d5c72c29903813eJake Slack                                _header.put(HttpTokens.CRLF);
100103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _needCRLF = false;
100203928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
100303928aee4356845252ac6b662d5c72c29903813eJake Slack                            BufferUtil.putHexInt(_header, size);
100403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.CRLF);
100503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
100603928aee4356845252ac6b662d5c72c29903813eJake Slack
100703928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Add end chunk trailer.
100803928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer.space() >= 2)
100903928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.put(HttpTokens.CRLF);
101003928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
101103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _needCRLF = true;
101203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
101303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
101403928aee4356845252ac6b662d5c72c29903813eJake Slack
101503928aee4356845252ac6b662d5c72c29903813eJake Slack                // If we need EOC and everything written
101603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_needEOC && (_content == null || _content.length() == 0))
101703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
101803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_header == null && _buffer == null)
101903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _header = _buffers.getHeader();
102003928aee4356845252ac6b662d5c72c29903813eJake Slack
102103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_needCRLF)
102203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
102303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length)
102403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
102503928aee4356845252ac6b662d5c72c29903813eJake Slack                            _header.put(HttpTokens.CRLF);
102603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _needCRLF = false;
102703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
102803928aee4356845252ac6b662d5c72c29903813eJake Slack                        else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length)
102903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
103003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.put(HttpTokens.CRLF);
103103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _needCRLF = false;
103203928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
103303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
103403928aee4356845252ac6b662d5c72c29903813eJake Slack
103503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!_needCRLF && _needEOC)
103603928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
103703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length)
103803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
103903928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (!_head)
104003928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
104103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _header.put(LAST_CHUNK);
104203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _bufferChunked=true;
104303928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
104403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _needEOC = false;
104503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
104603928aee4356845252ac6b662d5c72c29903813eJake Slack                        else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length)
104703928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
104803928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (!_head)
104903928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
105003928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer.put(LAST_CHUNK);
105103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _bufferChunked=true;
105203928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
105303928aee4356845252ac6b662d5c72c29903813eJake Slack                            _needEOC = false;
105403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
105503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
105603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
105703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
105803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
105903928aee4356845252ac6b662d5c72c29903813eJake Slack
106003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_content != null && _content.length() == 0)
106103928aee4356845252ac6b662d5c72c29903813eJake Slack            _content = null;
106203928aee4356845252ac6b662d5c72c29903813eJake Slack
106303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
106403928aee4356845252ac6b662d5c72c29903813eJake Slack
106503928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getBytesBuffered()
106603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
106703928aee4356845252ac6b662d5c72c29903813eJake Slack        return(_header==null?0:_header.length())+
106803928aee4356845252ac6b662d5c72c29903813eJake Slack        (_buffer==null?0:_buffer.length())+
106903928aee4356845252ac6b662d5c72c29903813eJake Slack        (_content==null?0:_content.length());
107003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
107103928aee4356845252ac6b662d5c72c29903813eJake Slack
107203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isEmpty()
107303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
107403928aee4356845252ac6b662d5c72c29903813eJake Slack        return (_header==null||_header.length()==0) &&
107503928aee4356845252ac6b662d5c72c29903813eJake Slack        (_buffer==null||_buffer.length()==0) &&
107603928aee4356845252ac6b662d5c72c29903813eJake Slack        (_content==null||_content.length()==0);
107703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
107803928aee4356845252ac6b662d5c72c29903813eJake Slack
107903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
108003928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
108103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
108203928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer header=_header;
108303928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer buffer=_buffer;
108403928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer content=_content;
108503928aee4356845252ac6b662d5c72c29903813eJake Slack        return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
108603928aee4356845252ac6b662d5c72c29903813eJake Slack                getClass().getSimpleName(),
108703928aee4356845252ac6b662d5c72c29903813eJake Slack                _state,
108803928aee4356845252ac6b662d5c72c29903813eJake Slack                header == null ? -1 : header.length(),
108903928aee4356845252ac6b662d5c72c29903813eJake Slack                buffer == null ? -1 : buffer.length(),
109003928aee4356845252ac6b662d5c72c29903813eJake Slack                content == null ? -1 : content.length());
109103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
109203928aee4356845252ac6b662d5c72c29903813eJake Slack}
1093