changeset 877:fef4392f4905

remove sendServerVersion
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 04 Oct 2016 14:36:51 -0600
parents 2efdb98f3543
children 5f8a242392da
files src/org/eclipse/jetty/http/AbstractGenerator.java src/org/eclipse/jetty/http/Generator.java src/org/eclipse/jetty/http/HttpGenerator.java src/org/eclipse/jetty/server/AbstractHttpConnection.java src/org/eclipse/jetty/server/Server.java
diffstat 5 files changed, 1393 insertions(+), 1429 deletions(-) [+]
line wrap: on
line diff
diff -r 2efdb98f3543 -r fef4392f4905 src/org/eclipse/jetty/http/AbstractGenerator.java
--- a/src/org/eclipse/jetty/http/AbstractGenerator.java	Tue Oct 04 14:05:45 2016 -0600
+++ b/src/org/eclipse/jetty/http/AbstractGenerator.java	Tue Oct 04 14:36:51 2016 -0600
@@ -40,493 +40,479 @@
  */
 public abstract class AbstractGenerator implements Generator
 {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class);
+	private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class);
 
-    // states
-    public final static int STATE_HEADER = 0;
-    public final static int STATE_CONTENT = 2;
-    public final static int STATE_FLUSHING = 3;
-    public final static int STATE_END = 4;
+	// states
+	public final static int STATE_HEADER = 0;
+	public final static int STATE_CONTENT = 2;
+	public final static int STATE_FLUSHING = 3;
+	public final static int STATE_END = 4;
 
-    public static final byte[] NO_BYTES = {};
+	public static final byte[] NO_BYTES = {};
 
-    // data
+	// data
 
-    protected final Buffers _buffers; // source of buffers
-    protected final EndPoint _endp;
+	protected final Buffers _buffers; // source of buffers
+	protected final EndPoint _endp;
 
-    protected int _state = STATE_HEADER;
+	protected int _state = STATE_HEADER;
 
-    protected int _status = 0;
-    protected int _version = HttpVersions.HTTP_1_1_ORDINAL;
-    protected  Buffer _reason;
-    protected  Buffer _method;
-    protected  String _uri;
+	protected int _status = 0;
+	protected int _version = HttpVersions.HTTP_1_1_ORDINAL;
+	protected  Buffer _reason;
+	protected  Buffer _method;
+	protected  String _uri;
 
-    protected long _contentWritten = 0;
-    protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
-    protected boolean _last = false;
-    protected boolean _head = false;
-    protected boolean _noContent = false;
-    protected Boolean _persistent = null;
+	protected long _contentWritten = 0;
+	protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
+	protected boolean _last = false;
+	protected boolean _head = false;
+	protected boolean _noContent = false;
+	protected Boolean _persistent = null;
 
-    protected Buffer _header; // Buffer for HTTP header (and maybe small _content)
-    protected Buffer _buffer; // Buffer for copy of passed _content
-    protected Buffer _content; // Buffer passed to addContent
+	protected Buffer _header; // Buffer for HTTP header (and maybe small _content)
+	protected Buffer _buffer; // Buffer for copy of passed _content
+	protected Buffer _content; // Buffer passed to addContent
 
-    protected Buffer _date;
-
-    private boolean _sendServerVersion;
+	protected Buffer _date;
 
 
-    /* ------------------------------------------------------------------------------- */
-    /**
-     * Constructor.
-     *
-     * @param buffers buffer pool
-     * @param io the end point
-     */
-    public AbstractGenerator(Buffers buffers, EndPoint io)
-    {
-        this._buffers = buffers;
-        this._endp = io;
-    }
+	/* ------------------------------------------------------------------------------- */
+	/**
+	 * Constructor.
+	 *
+	 * @param buffers buffer pool
+	 * @param io the end point
+	 */
+	public AbstractGenerator(Buffers buffers, EndPoint io)
+	{
+		this._buffers = buffers;
+		this._endp = io;
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    public abstract boolean isRequest();
+	/* ------------------------------------------------------------------------------- */
+	public abstract boolean isRequest();
 
-    /* ------------------------------------------------------------------------------- */
-    public abstract boolean isResponse();
+	/* ------------------------------------------------------------------------------- */
+	public abstract boolean isResponse();
 
-    /* ------------------------------------------------------------------------------- */
-    public boolean isOpen()
-    {
-        return _endp.isOpen();
-    }
+	/* ------------------------------------------------------------------------------- */
+	public boolean isOpen()
+	{
+		return _endp.isOpen();
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    public void reset()
-    {
-        _state = STATE_HEADER;
-        _status = 0;
-        _version = HttpVersions.HTTP_1_1_ORDINAL;
-        _reason = null;
-        _last = false;
-        _head = false;
-        _noContent=false;
-        _persistent = null;
-        _contentWritten = 0;
-        _contentLength = HttpTokens.UNKNOWN_CONTENT;
-        _date = null;
+	/* ------------------------------------------------------------------------------- */
+	public void reset()
+	{
+		_state = STATE_HEADER;
+		_status = 0;
+		_version = HttpVersions.HTTP_1_1_ORDINAL;
+		_reason = null;
+		_last = false;
+		_head = false;
+		_noContent=false;
+		_persistent = null;
+		_contentWritten = 0;
+		_contentLength = HttpTokens.UNKNOWN_CONTENT;
+		_date = null;
 
-        _content = null;
-        _method=null;
-    }
+		_content = null;
+		_method=null;
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    public void returnBuffers()
-    {
-        if (_buffer!=null && _buffer.length()==0)
-        {
-            _buffers.returnBuffer(_buffer);
-            _buffer=null;
-        }
+	/* ------------------------------------------------------------------------------- */
+	public void returnBuffers()
+	{
+		if (_buffer!=null && _buffer.length()==0)
+		{
+			_buffers.returnBuffer(_buffer);
+			_buffer=null;
+		}
 
-        if (_header!=null && _header.length()==0)
-        {
-            _buffers.returnBuffer(_header);
-            _header=null;
-        }
-    }
+		if (_header!=null && _header.length()==0)
+		{
+			_buffers.returnBuffer(_header);
+			_header=null;
+		}
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    public void resetBuffer()
-    {
-        if(_state>=STATE_FLUSHING)
-            throw new IllegalStateException("Flushed");
+	/* ------------------------------------------------------------------------------- */
+	public void resetBuffer()
+	{
+		if(_state>=STATE_FLUSHING)
+			throw new IllegalStateException("Flushed");
 
-        _last = false;
-        _persistent=null;
-        _contentWritten = 0;
-        _contentLength = HttpTokens.UNKNOWN_CONTENT;
-        _content=null;
-        if (_buffer!=null)
-            _buffer.clear();
-    }
+		_last = false;
+		_persistent=null;
+		_contentWritten = 0;
+		_contentLength = HttpTokens.UNKNOWN_CONTENT;
+		_content=null;
+		if (_buffer!=null)
+			_buffer.clear();
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Returns the contentBufferSize.
-     */
-    public int getContentBufferSize()
-    {
-        if (_buffer==null)
-            _buffer=_buffers.getBuffer();
-        return _buffer.capacity();
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @return Returns the contentBufferSize.
+	 */
+	public int getContentBufferSize()
+	{
+		if (_buffer==null)
+			_buffer=_buffers.getBuffer();
+		return _buffer.capacity();
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @param contentBufferSize The contentBufferSize to set.
-     */
-    public void increaseContentBufferSize(int contentBufferSize)
-    {
-        if (_buffer==null)
-            _buffer=_buffers.getBuffer();
-        if (contentBufferSize > _buffer.capacity())
-        {
-            Buffer nb = _buffers.getBuffer(contentBufferSize);
-            nb.put(_buffer);
-            _buffers.returnBuffer(_buffer);
-            _buffer = nb;
-        }
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @param contentBufferSize The contentBufferSize to set.
+	 */
+	public void increaseContentBufferSize(int contentBufferSize)
+	{
+		if (_buffer==null)
+			_buffer=_buffers.getBuffer();
+		if (contentBufferSize > _buffer.capacity())
+		{
+			Buffer nb = _buffers.getBuffer(contentBufferSize);
+			nb.put(_buffer);
+			_buffers.returnBuffer(_buffer);
+			_buffer = nb;
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    public Buffer getUncheckedBuffer()
-    {
-        return _buffer;
-    }
+	/* ------------------------------------------------------------ */
+	public Buffer getUncheckedBuffer()
+	{
+		return _buffer;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean getSendServerVersion ()
-    {
-        return _sendServerVersion;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setSendServerVersion (boolean sendServerVersion)
-    {
-        _sendServerVersion = sendServerVersion;
-    }
+	/* ------------------------------------------------------------ */
+	public int getState()
+	{
+		return _state;
+	}
 
-    /* ------------------------------------------------------------ */
-    public int getState()
-    {
-        return _state;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isState(int state)
+	{
+		return _state == state;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isState(int state)
-    {
-        return _state == state;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isComplete()
+	{
+		return _state == STATE_END;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isComplete()
-    {
-        return _state == STATE_END;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isIdle()
+	{
+		return _state == STATE_HEADER && _method==null && _status==0;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isIdle()
-    {
-        return _state == STATE_HEADER && _method==null && _status==0;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isCommitted()
+	{
+		return _state != STATE_HEADER;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isCommitted()
-    {
-        return _state != STATE_HEADER;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @return Returns the head.
+	 */
+	public boolean isHead()
+	{
+		return _head;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Returns the head.
-     */
-    public boolean isHead()
-    {
-        return _head;
-    }
+	/* ------------------------------------------------------------ */
+	public void setContentLength(long value)
+	{
+		if (value<0)
+			_contentLength=HttpTokens.UNKNOWN_CONTENT;
+		else
+			_contentLength=value;
+	}
 
-    /* ------------------------------------------------------------ */
-    public void setContentLength(long value)
-    {
-        if (value<0)
-            _contentLength=HttpTokens.UNKNOWN_CONTENT;
-        else
-            _contentLength=value;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @param head The head to set.
+	 */
+	public void setHead(boolean head)
+	{
+		_head = head;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @param head The head to set.
-     */
-    public void setHead(boolean head)
-    {
-        _head = head;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @return <code>false</code> if the connection should be closed after a request has been read,
+	 * <code>true</code> if it should be used for additional requests.
+	 */
+	public boolean isPersistent()
+	{
+		return _persistent!=null
+		?_persistent.booleanValue()
+		:(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL);
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @return <code>false</code> if the connection should be closed after a request has been read,
-     * <code>true</code> if it should be used for additional requests.
-     */
-    public boolean isPersistent()
-    {
-        return _persistent!=null
-        ?_persistent.booleanValue()
-        :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL);
-    }
+	/* ------------------------------------------------------------ */
+	public void setPersistent(boolean persistent)
+	{
+		_persistent=persistent;
+	}
 
-    /* ------------------------------------------------------------ */
-    public void setPersistent(boolean persistent)
-    {
-        _persistent=persistent;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @param version The version of the client the response is being sent to (NB. Not the version
-     *            in the response, which is the version of the server).
-     */
-    public void setVersion(int version)
-    {
-        if (_state != STATE_HEADER)
-            throw new IllegalStateException("STATE!=START "+_state);
-        _version = version;
-        if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null)
-            _noContent=true;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @param version The version of the client the response is being sent to (NB. Not the version
+	 *            in the response, which is the version of the server).
+	 */
+	public void setVersion(int version)
+	{
+		if (_state != STATE_HEADER)
+			throw new IllegalStateException("STATE!=START "+_state);
+		_version = version;
+		if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null)
+			_noContent=true;
+	}
 
-    /* ------------------------------------------------------------ */
-    public int getVersion()
-    {
-        return _version;
-    }
+	/* ------------------------------------------------------------ */
+	public int getVersion()
+	{
+		return _version;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer)
-     */
-    public void setDate(Buffer timeStampBuffer)
-    {
-        _date=timeStampBuffer;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer)
+	 */
+	public void setDate(Buffer timeStampBuffer)
+	{
+		_date=timeStampBuffer;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     */
-    public void setRequest(String method, String uri)
-    {
-        if (method==null || HttpMethods.GET.equals(method) )
-            _method=HttpMethods.GET_BUFFER;
-        else
-            _method=HttpMethods.CACHE.lookup(method);
-        _uri=uri;
-        if (_version==HttpVersions.HTTP_0_9_ORDINAL)
-            _noContent=true;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 */
+	public void setRequest(String method, String uri)
+	{
+		if (method==null || HttpMethods.GET.equals(method) )
+			_method=HttpMethods.GET_BUFFER;
+		else
+			_method=HttpMethods.CACHE.lookup(method);
+		_uri=uri;
+		if (_version==HttpVersions.HTTP_0_9_ORDINAL)
+			_noContent=true;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @param status The status code to send.
-     * @param reason the status message to send.
-     */
-    public void setResponse(int status, String reason)
-    {
-        if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START");
-        _method=null;
-        _status = status;
-        if (reason!=null)
-        {
-            int len=reason.length();
+	/* ------------------------------------------------------------ */
+	/**
+	 * @param status The status code to send.
+	 * @param reason the status message to send.
+	 */
+	public void setResponse(int status, String reason)
+	{
+		if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START");
+		_method=null;
+		_status = status;
+		if (reason!=null)
+		{
+			int len=reason.length();
 
-            // TODO don't hard code
-            if (len>1024)
-                len=1024;
-            _reason=new ByteArrayBuffer(len);
-            for (int i=0;i<len;i++)
-            {
-                char ch = reason.charAt(i);
-                if (ch!='\r'&&ch!='\n')
-                    _reason.put((byte)ch);
-                else
-                    _reason.put((byte)' ');
-            }
-        }
-    }
+			// TODO don't hard code
+			if (len>1024)
+				len=1024;
+			_reason=new ByteArrayBuffer(len);
+			for (int i=0;i<len;i++)
+			{
+				char ch = reason.charAt(i);
+				if (ch!='\r'&&ch!='\n')
+					_reason.put((byte)ch);
+				else
+					_reason.put((byte)' ');
+			}
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    /** Prepare buffer for unchecked writes.
-     * Prepare the generator buffer to receive unchecked writes
-     * @return the available space in the buffer.
-     * @throws IOException
-     */
-    public abstract int prepareUncheckedAddContent() throws IOException;
+	/* ------------------------------------------------------------ */
+	/** Prepare buffer for unchecked writes.
+	 * Prepare the generator buffer to receive unchecked writes
+	 * @return the available space in the buffer.
+	 * @throws IOException
+	 */
+	public abstract int prepareUncheckedAddContent() throws IOException;
 
-    /* ------------------------------------------------------------ */
-    void uncheckedAddContent(int b)
-    {
-        _buffer.put((byte)b);
-    }
+	/* ------------------------------------------------------------ */
+	void uncheckedAddContent(int b)
+	{
+		_buffer.put((byte)b);
+	}
 
-    /* ------------------------------------------------------------ */
-    public void completeUncheckedAddContent()
-    {
-        if (_noContent)
-        {
-            if(_buffer!=null)
-                _buffer.clear();
-        }
-        else
-        {
-            _contentWritten+=_buffer.length();
-            if (_head)
-                _buffer.clear();
-        }
-    }
+	/* ------------------------------------------------------------ */
+	public void completeUncheckedAddContent()
+	{
+		if (_noContent)
+		{
+			if(_buffer!=null)
+				_buffer.clear();
+		}
+		else
+		{
+			_contentWritten+=_buffer.length();
+			if (_head)
+				_buffer.clear();
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isBufferFull()
-    {
-        if (_buffer != null && _buffer.space()==0)
-        {
-            if (_buffer.length()==0 && !_buffer.isImmutable())
-                _buffer.compact();
-            return _buffer.space()==0;
-        }
+	/* ------------------------------------------------------------ */
+	public boolean isBufferFull()
+	{
+		if (_buffer != null && _buffer.space()==0)
+		{
+			if (_buffer.length()==0 && !_buffer.isImmutable())
+				_buffer.compact();
+			return _buffer.space()==0;
+		}
 
-        return _content!=null && _content.length()>0;
-    }
+		return _content!=null && _content.length()>0;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isWritten()
-    {
-        return _contentWritten>0;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isWritten()
+	{
+		return _contentWritten>0;
+	}
 
-    /* ------------------------------------------------------------ */
-    public boolean isAllContentWritten()
-    {
-        return _contentLength>=0 && _contentWritten>=_contentLength;
-    }
+	/* ------------------------------------------------------------ */
+	public boolean isAllContentWritten()
+	{
+		return _contentLength>=0 && _contentWritten>=_contentLength;
+	}
 
-    /* ------------------------------------------------------------ */
-    public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException;
+	/* ------------------------------------------------------------ */
+	public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException;
 
-    /* ------------------------------------------------------------ */
-    /**
-     * Complete the message.
-     *
-     * @throws IOException
-     */
-    public void complete() throws IOException
-    {
-        if (_state == STATE_HEADER)
-        {
-            throw new IllegalStateException("State==HEADER");
-        }
+	/* ------------------------------------------------------------ */
+	/**
+	 * Complete the message.
+	 *
+	 * @throws IOException
+	 */
+	public void complete() throws IOException
+	{
+		if (_state == STATE_HEADER)
+		{
+			throw new IllegalStateException("State==HEADER");
+		}
 
-        if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
-        {
-            if (LOG.isDebugEnabled())
-                LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
-            _persistent = false;
-        }
-    }
+		if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
+		{
+			if (LOG.isDebugEnabled())
+				LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
+			_persistent = false;
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    public abstract int flushBuffer() throws IOException;
+	/* ------------------------------------------------------------ */
+	public abstract int flushBuffer() throws IOException;
 
 
-    /* ------------------------------------------------------------ */
-    public void flush(long maxIdleTime) throws IOException
-    {
-        // block until everything is flushed
-        long now=System.currentTimeMillis();
-        long end=now+maxIdleTime;
-        Buffer content = _content;
-        Buffer buffer = _buffer;
-        if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull())
-        {
-            flushBuffer();
+	/* ------------------------------------------------------------ */
+	public void flush(long maxIdleTime) throws IOException
+	{
+		// block until everything is flushed
+		long now=System.currentTimeMillis();
+		long end=now+maxIdleTime;
+		Buffer content = _content;
+		Buffer buffer = _buffer;
+		if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull())
+		{
+			flushBuffer();
 
-            while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown())
-            {
-                blockForOutput(end-now);
-                now=System.currentTimeMillis();
-            }
-        }
-    }
+			while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown())
+			{
+				blockForOutput(end-now);
+				now=System.currentTimeMillis();
+			}
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * Utility method to send an error response. If the builder is not committed, this call is
-     * equivalent to a setResponse, addContent and complete call.
-     *
-     * @param code The error code
-     * @param reason The error reason
-     * @param content Contents of the error page
-     * @param close True if the connection should be closed
-     * @throws IOException if there is a problem flushing the response
-     */
-    public void sendError(int code, String reason, String content, boolean close) throws IOException
-    {
-        if (close)
-            _persistent=false;
-        if (isCommitted())
-        {
-            LOG.debug("sendError on committed: {} {}",code,reason);
-        }
-        else
-        {
-            LOG.debug("sendError: {} {}",code,reason);
-            setResponse(code, reason);
-            if (content != null)
-            {
-                completeHeader(null, false);
-                addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
-            }
-            else if (code>=400)
-            {
-                completeHeader(null, false);
-                addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST);
-            }
-            else
-            {
-                completeHeader(null, true);
-            }
-            complete();
-        }
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * Utility method to send an error response. If the builder is not committed, this call is
+	 * equivalent to a setResponse, addContent and complete call.
+	 *
+	 * @param code The error code
+	 * @param reason The error reason
+	 * @param content Contents of the error page
+	 * @param close True if the connection should be closed
+	 * @throws IOException if there is a problem flushing the response
+	 */
+	public void sendError(int code, String reason, String content, boolean close) throws IOException
+	{
+		if (close)
+			_persistent=false;
+		if (isCommitted())
+		{
+			LOG.debug("sendError on committed: {} {}",code,reason);
+		}
+		else
+		{
+			LOG.debug("sendError: {} {}",code,reason);
+			setResponse(code, reason);
+			if (content != null)
+			{
+				completeHeader(null, false);
+				addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
+			}
+			else if (code>=400)
+			{
+				completeHeader(null, false);
+				addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST);
+			}
+			else
+			{
+				completeHeader(null, true);
+			}
+			complete();
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Returns the contentWritten.
-     */
-    public long getContentWritten()
-    {
-        return _contentWritten;
-    }
+	/* ------------------------------------------------------------ */
+	/**
+	 * @return Returns the contentWritten.
+	 */
+	public long getContentWritten()
+	{
+		return _contentWritten;
+	}
 
 
 
-    /* ------------------------------------------------------------ */
-    public void  blockForOutput(long maxIdleTime) throws IOException
-    {
-        if (_endp.isBlocking())
-        {
-            try
-            {
-                flushBuffer();
-            }
-            catch(IOException e)
-            {
-                _endp.close();
-                throw e;
-            }
-        }
-        else
-        {
-            if (!_endp.blockWritable(maxIdleTime))
-            {
-                _endp.close();
-                throw new EofException("timeout");
-            }
+	/* ------------------------------------------------------------ */
+	public void  blockForOutput(long maxIdleTime) throws IOException
+	{
+		if (_endp.isBlocking())
+		{
+			try
+			{
+				flushBuffer();
+			}
+			catch(IOException e)
+			{
+				_endp.close();
+				throw e;
+			}
+		}
+		else
+		{
+			if (!_endp.blockWritable(maxIdleTime))
+			{
+				_endp.close();
+				throw new EofException("timeout");
+			}
 
-            flushBuffer();
-        }
-    }
+			flushBuffer();
+		}
+	}
 
 }
diff -r 2efdb98f3543 -r fef4392f4905 src/org/eclipse/jetty/http/Generator.java
--- a/src/org/eclipse/jetty/http/Generator.java	Tue Oct 04 14:05:45 2016 -0600
+++ b/src/org/eclipse/jetty/http/Generator.java	Tue Oct 04 14:36:51 2016 -0600
@@ -25,72 +25,70 @@
 
 public interface Generator
 {
-    public static final boolean LAST=true;
-    public static final boolean MORE=false;
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Add content.
-     * 
-     * @param content
-     * @param last
-     * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
-     * @throws IllegalStateException If the request is not expecting any more content,
-     *   or if the buffers are full and cannot be flushed.
-     * @throws IOException if there is a problem flushing the buffers.
-     */
-    void addContent(Buffer content, boolean last) throws IOException;
+	public static final boolean LAST=true;
+	public static final boolean MORE=false;
 
-    void complete() throws IOException;
-
-    void completeHeader(HttpFields responseFields, boolean last) throws IOException;
-
-    int flushBuffer() throws IOException;
-
-    int getContentBufferSize();
+	/* ------------------------------------------------------------ */
+	/**
+	 * Add content.
+	 * 
+	 * @param content
+	 * @param last
+	 * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
+	 * @throws IllegalStateException If the request is not expecting any more content,
+	 *   or if the buffers are full and cannot be flushed.
+	 * @throws IOException if there is a problem flushing the buffers.
+	 */
+	void addContent(Buffer content, boolean last) throws IOException;
 
-    long getContentWritten();
+	void complete() throws IOException;
+
+	void completeHeader(HttpFields responseFields, boolean last) throws IOException;
+
+	int flushBuffer() throws IOException;
 
-    boolean isWritten();
-    
-    boolean isAllContentWritten();
+	int getContentBufferSize();
+
+	long getContentWritten();
 
-    void increaseContentBufferSize(int size);
-    
-    boolean isBufferFull();
+	boolean isWritten();
+	
+	boolean isAllContentWritten();
 
-    boolean isCommitted();
-
-    boolean isComplete();
+	void increaseContentBufferSize(int size);
+	
+	boolean isBufferFull();
 
-    boolean isPersistent();
+	boolean isCommitted();
 
-    void reset();
+	boolean isComplete();
 
-    void resetBuffer();
-    
-    void returnBuffers();
+	boolean isPersistent();
+
+	void reset();
 
-    void sendError(int code, String reason, String content, boolean close) throws IOException;
-    
-    void setHead(boolean head);
+	void resetBuffer();
+	
+	void returnBuffers();
 
-    void setRequest(String method, String uri);
-
-    void setResponse(int status, String reason);
+	void sendError(int code, String reason, String content, boolean close) throws IOException;
+	
+	void setHead(boolean head);
 
+	void setRequest(String method, String uri);
 
-    void setSendServerVersion(boolean sendServerVersion);
- 
-    void setVersion(int version);
+	void setResponse(int status, String reason);
 
-    boolean isIdle();
+ 
+	void setVersion(int version);
+
+	boolean isIdle();
 
-    void setContentLength(long length);
-    
-    void setPersistent(boolean persistent);
+	void setContentLength(long length);
+	
+	void setPersistent(boolean persistent);
 
-    void setDate(Buffer timeStampBuffer);
-    
+	void setDate(Buffer timeStampBuffer);
+	
 
 }
diff -r 2efdb98f3543 -r fef4392f4905 src/org/eclipse/jetty/http/HttpGenerator.java
--- a/src/org/eclipse/jetty/http/HttpGenerator.java	Tue Oct 04 14:05:45 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpGenerator.java	Tue Oct 04 14:36:51 2016 -0600
@@ -41,1052 +41,1049 @@
  */
 public class HttpGenerator extends AbstractGenerator
 {
-    private static final Logger LOG = LoggerFactory.getLogger(HttpGenerator.class);
+	private static final Logger LOG = LoggerFactory.getLogger(HttpGenerator.class);
 
-    // Build cache of response lines for status
-    private static class Status
-    {
-        Buffer _reason;
-        Buffer _schemeCode;
-        Buffer _responseLine;
-    }
-    private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1];
-    static
-    {
-        int versionLength=HttpVersions.HTTP_1_1_BUFFER.length();
+	// Build cache of response lines for status
+	private static class Status
+	{
+		Buffer _reason;
+		Buffer _schemeCode;
+		Buffer _responseLine;
+	}
+	private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1];
+	static
+	{
+		int versionLength=HttpVersions.HTTP_1_1_BUFFER.length();
 
-        for (int i=0;i<__status.length;i++)
-        {
-            HttpStatus.Code code = HttpStatus.getCode(i);
-            if (code==null)
-                continue;
-            String reason=code.getMessage();
-            byte[] bytes=new byte[versionLength+5+reason.length()+2];
-            HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength);
-            bytes[versionLength+0]=' ';
-            bytes[versionLength+1]=(byte)('0'+i/100);
-            bytes[versionLength+2]=(byte)('0'+(i%100)/10);
-            bytes[versionLength+3]=(byte)('0'+(i%10));
-            bytes[versionLength+4]=' ';
-            for (int j=0;j<reason.length();j++)
-                bytes[versionLength+5+j]=(byte)reason.charAt(j);
-            bytes[versionLength+5+reason.length()]=HttpTokens.CARRIAGE_RETURN;
-            bytes[versionLength+6+reason.length()]=HttpTokens.LINE_FEED;
+		for (int i=0;i<__status.length;i++)
+		{
+			HttpStatus.Code code = HttpStatus.getCode(i);
+			if (code==null)
+				continue;
+			String reason=code.getMessage();
+			byte[] bytes=new byte[versionLength+5+reason.length()+2];
+			HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength);
+			bytes[versionLength+0]=' ';
+			bytes[versionLength+1]=(byte)('0'+i/100);
+			bytes[versionLength+2]=(byte)('0'+(i%100)/10);
+			bytes[versionLength+3]=(byte)('0'+(i%10));
+			bytes[versionLength+4]=' ';
+			for (int j=0;j<reason.length();j++)
+				bytes[versionLength+5+j]=(byte)reason.charAt(j);
+			bytes[versionLength+5+reason.length()]=HttpTokens.CARRIAGE_RETURN;
+			bytes[versionLength+6+reason.length()]=HttpTokens.LINE_FEED;
 
-            __status[i] = new Status();
-            __status[i]._reason=new ByteArrayBuffer(bytes,versionLength+5,bytes.length-versionLength-7,Buffer.IMMUTABLE);
-            __status[i]._schemeCode=new ByteArrayBuffer(bytes,0,versionLength+5,Buffer.IMMUTABLE);
-            __status[i]._responseLine=new ByteArrayBuffer(bytes,0,bytes.length,Buffer.IMMUTABLE);
-        }
-    }
+			__status[i] = new Status();
+			__status[i]._reason=new ByteArrayBuffer(bytes,versionLength+5,bytes.length-versionLength-7,Buffer.IMMUTABLE);
+			__status[i]._schemeCode=new ByteArrayBuffer(bytes,0,versionLength+5,Buffer.IMMUTABLE);
+			__status[i]._responseLine=new ByteArrayBuffer(bytes,0,bytes.length,Buffer.IMMUTABLE);
+		}
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    public static Buffer getReasonBuffer(int code)
-    {
-        Status status = code<__status.length?__status[code]:null;
-        if (status!=null)
-            return status._reason;
-        return null;
-    }
+	/* ------------------------------------------------------------------------------- */
+	public static Buffer getReasonBuffer(int code)
+	{
+		Status status = code<__status.length?__status[code]:null;
+		if (status!=null)
+			return status._reason;
+		return null;
+	}
 
 
-    // common _content
-    private static final byte[] LAST_CHUNK =
-    { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'};
-    private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012");
-    private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012");
-    private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012");
-    private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: ");
-    private static final byte[] CRLF = StringUtil.getBytes("\015\012");
-    private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
-    private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012");
+	// common _content
+	private static final byte[] LAST_CHUNK =
+	{ (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'};
+	private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012");
+	private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012");
+	private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012");
+	private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: ");
+	private static final byte[] CRLF = StringUtil.getBytes("\015\012");
+	private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012");
+	private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012");
 
-    // other statics
-    private static final int CHUNK_SPACE = 12;
+	// other statics
+	private static final int CHUNK_SPACE = 12;
 
-    public static void setServerVersion(String version)
-    {
-        SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012");
-    }
+	public static void setServerVersion(String version)
+	{
+		SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012");
+	}
 
-    // data
-    protected boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer
-    private boolean _needCRLF = false;
-    private boolean _needEOC = false;
-    private boolean _bufferChunked = false;
+	// data
+	protected boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer
+	private boolean _needCRLF = false;
+	private boolean _needEOC = false;
+	private boolean _bufferChunked = false;
 
 
-    /* ------------------------------------------------------------------------------- */
-    /**
-     * Constructor.
-     *
-     * @param buffers buffer pool
-     * @param io the end point to use
-     */
-    public HttpGenerator(Buffers buffers, EndPoint io)
-    {
-        super(buffers,io);
-    }
+	/* ------------------------------------------------------------------------------- */
+	/**
+	 * Constructor.
+	 *
+	 * @param buffers buffer pool
+	 * @param io the end point to use
+	 */
+	public HttpGenerator(Buffers buffers, EndPoint io)
+	{
+		super(buffers,io);
+	}
 
-    /* ------------------------------------------------------------------------------- */
-    @Override
-    public void reset()
-    {
-        if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
-        {
-            try
-            {
-                _endp.shutdownOutput();
-            }
-            catch(IOException e)
-            {
-                LOG.trace("",e);
-            }
-        }
-        super.reset();
-        if (_buffer!=null)
-            _buffer.clear();
-        if (_header!=null)
-            _header.clear();
-        if (_content!=null)
-            _content=null;
-        _bypass = false;
-        _needCRLF = false;
-        _needEOC = false;
-        _bufferChunked=false;
-        _method=null;
-        _uri=null;
-        _noContent=false;
-    }
+	/* ------------------------------------------------------------------------------- */
+	@Override
+	public void reset()
+	{
+		if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
+		{
+			try
+			{
+				_endp.shutdownOutput();
+			}
+			catch(IOException e)
+			{
+				LOG.trace("",e);
+			}
+		}
+		super.reset();
+		if (_buffer!=null)
+			_buffer.clear();
+		if (_header!=null)
+			_header.clear();
+		if (_content!=null)
+			_content=null;
+		_bypass = false;
+		_needCRLF = false;
+		_needEOC = false;
+		_bufferChunked=false;
+		_method=null;
+		_uri=null;
+		_noContent=false;
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * Add content.
-     *
-     * @param content
-     * @param last
-     * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
-     * @throws IllegalStateException If the request is not expecting any more content,
-     *   or if the buffers are full and cannot be flushed.
-     * @throws IOException if there is a problem flushing the buffers.
-     */
-    public void addContent(Buffer content, boolean last) throws IOException
-    {
-        if (_noContent)
-            throw new IllegalStateException("NO CONTENT");
+	/* ------------------------------------------------------------ */
+	/**
+	 * Add content.
+	 *
+	 * @param content
+	 * @param last
+	 * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}.
+	 * @throws IllegalStateException If the request is not expecting any more content,
+	 *   or if the buffers are full and cannot be flushed.
+	 * @throws IOException if there is a problem flushing the buffers.
+	 */
+	public void addContent(Buffer content, boolean last) throws IOException
+	{
+		if (_noContent)
+			throw new IllegalStateException("NO CONTENT");
 
-        if (_last || _state==STATE_END)
-        {
-            LOG.warn("Ignoring extra content {}",content);
-            content.clear();
-            return;
-        }
-        _last = last;
+		if (_last || _state==STATE_END)
+		{
+			LOG.warn("Ignoring extra content {}",content);
+			content.clear();
+			return;
+		}
+		_last = last;
 
-        // Handle any unfinished business?
-        if (_content!=null && _content.length()>0 || _bufferChunked)
-        {
-            if (_endp.isOutputShutdown())
-                throw new EofException();
-            flushBuffer();
-            if (_content != null && _content.length()>0)
-            {
-                if (_bufferChunked)
-                {
-                    Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length());
-                    nc.put(_content);
-                    nc.put(HttpTokens.CRLF);
-                    BufferUtil.putHexInt(nc, content.length());
-                    nc.put(HttpTokens.CRLF);
-                    nc.put(content);
-                    content=nc;
-                }
-                else
-                {
-                    Buffer nc=_buffers.getBuffer(_content.length()+content.length());
-                    nc.put(_content);
-                    nc.put(content);
-                    content=nc;
-                }
-            }
-        }
+		// Handle any unfinished business?
+		if (_content!=null && _content.length()>0 || _bufferChunked)
+		{
+			if (_endp.isOutputShutdown())
+				throw new EofException();
+			flushBuffer();
+			if (_content != null && _content.length()>0)
+			{
+				if (_bufferChunked)
+				{
+					Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length());
+					nc.put(_content);
+					nc.put(HttpTokens.CRLF);
+					BufferUtil.putHexInt(nc, content.length());
+					nc.put(HttpTokens.CRLF);
+					nc.put(content);
+					content=nc;
+				}
+				else
+				{
+					Buffer nc=_buffers.getBuffer(_content.length()+content.length());
+					nc.put(_content);
+					nc.put(content);
+					content=nc;
+				}
+			}
+		}
 
-        _content = content;
-        _contentWritten += content.length();
+		_content = content;
+		_contentWritten += content.length();
 
-        // Handle the _content
-        if (_head)
-        {
-            content.clear();
-            _content=null;
-        }
-        else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024))
-        {
-            _bypass = true;
-        }
-        else if (!_bufferChunked)
-        {
-            // Yes - so we better check we have a buffer
-            if (_buffer == null)
-                _buffer = _buffers.getBuffer();
+		// Handle the _content
+		if (_head)
+		{
+			content.clear();
+			_content=null;
+		}
+		else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024))
+		{
+			_bypass = true;
+		}
+		else if (!_bufferChunked)
+		{
+			// Yes - so we better check we have a buffer
+			if (_buffer == null)
+				_buffer = _buffers.getBuffer();
 
-            // Copy _content to buffer;
-            int len=_buffer.put(_content);
-            _content.skip(len);
-            if (_content.length() == 0)
-                _content = null;
-        }
-    }
+			// Copy _content to buffer;
+			int len=_buffer.put(_content);
+			_content.skip(len);
+			if (_content.length() == 0)
+				_content = null;
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * send complete response.
-     *
-     * @param response
-     */
-    public void sendResponse(Buffer response) throws IOException
-    {
-        if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head )
-            throw new IllegalStateException();
+	/* ------------------------------------------------------------ */
+	/**
+	 * send complete response.
+	 *
+	 * @param response
+	 */
+	public void sendResponse(Buffer response) throws IOException
+	{
+		if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head )
+			throw new IllegalStateException();
 
-        _last = true;
+		_last = true;
 
-        _content = response;
-        _bypass = true;
-        _state = STATE_FLUSHING;
+		_content = response;
+		_bypass = true;
+		_state = STATE_FLUSHING;
 
-        // TODO this is not exactly right, but should do.
-        _contentLength =_contentWritten = response.length();
+		// TODO this is not exactly right, but should do.
+		_contentLength =_contentWritten = response.length();
 
-    }
+	}
 
-    /* ------------------------------------------------------------ */
-    /** Prepare buffer for unchecked writes.
-     * Prepare the generator buffer to receive unchecked writes
-     * @return the available space in the buffer.
-     * @throws IOException
-     */
-    @Override
-    public int prepareUncheckedAddContent() throws IOException
-    {
-        if (_noContent)
-            return -1;
+	/* ------------------------------------------------------------ */
+	/** Prepare buffer for unchecked writes.
+	 * Prepare the generator buffer to receive unchecked writes
+	 * @return the available space in the buffer.
+	 * @throws IOException
+	 */
+	@Override
+	public int prepareUncheckedAddContent() throws IOException
+	{
+		if (_noContent)
+			return -1;
 
-        if (_last || _state==STATE_END)
-            return -1;
+		if (_last || _state==STATE_END)
+			return -1;
 
-        // Handle any unfinished business?
-        Buffer content = _content;
-        if (content != null && content.length()>0 || _bufferChunked)
-        {
-            flushBuffer();
-            if (content != null && content.length()>0 || _bufferChunked)
-                throw new IllegalStateException("FULL");
-        }
+		// Handle any unfinished business?
+		Buffer content = _content;
+		if (content != null && content.length()>0 || _bufferChunked)
+		{
+			flushBuffer();
+			if (content != null && content.length()>0 || _bufferChunked)
+				throw new IllegalStateException("FULL");
+		}
 
-        // we better check we have a buffer
-        if (_buffer == null)
-            _buffer = _buffers.getBuffer();
+		// we better check we have a buffer
+		if (_buffer == null)
+			_buffer = _buffers.getBuffer();
 
-        _contentWritten-=_buffer.length();
+		_contentWritten-=_buffer.length();
 
-        // Handle the _content
-        if (_head)
-            return Integer.MAX_VALUE;
+		// Handle the _content
+		if (_head)
+			return Integer.MAX_VALUE;
 
-        return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0);
-    }
+		return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0);
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public boolean isBufferFull()
-    {
-        // Should we flush the buffers?
-        return super.isBufferFull() || _bufferChunked || _bypass  || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE);
-    }
+	/* ------------------------------------------------------------ */
+	@Override
+	public boolean isBufferFull()
+	{
+		// Should we flush the buffers?
+		return super.isBufferFull() || _bufferChunked || _bypass  || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE);
+	}
 
-    /* ------------------------------------------------------------ */
-    public void send1xx(int code) throws IOException
-    {
-        if (_state != STATE_HEADER)
-            return;
+	/* ------------------------------------------------------------ */
+	public void send1xx(int code) throws IOException
+	{
+		if (_state != STATE_HEADER)
+			return;
 
-        if (code<100||code>199)
-            throw new IllegalArgumentException("!1xx");
-        Status status=__status[code];
-        if (status==null)
-            throw new IllegalArgumentException(code+"?");
+		if (code<100||code>199)
+			throw new IllegalArgumentException("!1xx");
+		Status status=__status[code];
+		if (status==null)
+			throw new IllegalArgumentException(code+"?");
 
-        // get a header buffer
-        if (_header == null)
-            _header = _buffers.getHeader();
+		// get a header buffer
+		if (_header == null)
+			_header = _buffers.getHeader();
 
-        _header.put(status._responseLine);
-        _header.put(HttpTokens.CRLF);
+		_header.put(status._responseLine);
+		_header.put(HttpTokens.CRLF);
 
-        try
-        {
-            // nasty semi busy flush!
-            while(_header.length()>0)
-            {
-                int len = _endp.flush(_header);
-                if (len<0)
-                    throw new EofException();
-                if (len==0)
-                    Thread.sleep(100);
-            }
-        }
-        catch(InterruptedException e)
-        {
-            LOG.debug("",e);
-            throw new InterruptedIOException(e.toString());
-        }
-    }
+		try
+		{
+			// nasty semi busy flush!
+			while(_header.length()>0)
+			{
+				int len = _endp.flush(_header);
+				if (len<0)
+					throw new EofException();
+				if (len==0)
+					Thread.sleep(100);
+			}
+		}
+		catch(InterruptedException e)
+		{
+			LOG.debug("",e);
+			throw new InterruptedIOException(e.toString());
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public boolean isRequest()
-    {
-        return _method!=null;
-    }
+	/* ------------------------------------------------------------ */
+	@Override
+	public boolean isRequest()
+	{
+		return _method!=null;
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public boolean isResponse()
-    {
-        return _method==null;
-    }
+	/* ------------------------------------------------------------ */
+	@Override
+	public boolean isResponse()
+	{
+		return _method==null;
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
-    {
-        if (_state != STATE_HEADER)
-            return;
+	/* ------------------------------------------------------------ */
+	@Override
+	public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
+	{
+		if (_state != STATE_HEADER)
+			return;
 
-        // handle a reset
-        if (isResponse() && _status==0)
-            throw new EofException();
+		// handle a reset
+		if (isResponse() && _status==0)
+			throw new EofException();
 
-        if (_last && !allContentAdded)
-            throw new IllegalStateException("last?");
-        _last = _last | allContentAdded;
+		if (_last && !allContentAdded)
+			throw new IllegalStateException("last?");
+		_last = _last | allContentAdded;
 
-        // get a header buffer
-        if (_header == null)
-            _header = _buffers.getHeader();
+		// get a header buffer
+		if (_header == null)
+			_header = _buffers.getHeader();
 
-        boolean has_server = false;
+		boolean has_server = false;
 
-        try
-        {
-            if (isRequest())
-            {
-                _persistent=true;
+		try
+		{
+			if (isRequest())
+			{
+				_persistent=true;
 
-                if (_version == HttpVersions.HTTP_0_9_ORDINAL)
-                {
-                    _contentLength = HttpTokens.NO_CONTENT;
-                    _header.put(_method);
-                    _header.put((byte)' ');
-                    _header.put(_uri.getBytes("UTF-8")); // TODO check
-                    _header.put(HttpTokens.CRLF);
-                    _state = STATE_FLUSHING;
-                    _noContent=true;
-                    return;
-                }
-                else
-                {
-                    _header.put(_method);
-                    _header.put((byte)' ');
-                    _header.put(_uri.getBytes("UTF-8")); // TODO check
-                    _header.put((byte)' ');
-                    _header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER);
-                    _header.put(HttpTokens.CRLF);
-                }
-            }
-            else
-            {
-                // Responses
-                if (_version == HttpVersions.HTTP_0_9_ORDINAL)
-                {
-                    _persistent = false;
-                    _contentLength = HttpTokens.EOF_CONTENT;
-                    _state = STATE_CONTENT;
-                    return;
-                }
-                else
-                {
-                    if (_persistent==null)
-                        _persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL);
+				if (_version == HttpVersions.HTTP_0_9_ORDINAL)
+				{
+					_contentLength = HttpTokens.NO_CONTENT;
+					_header.put(_method);
+					_header.put((byte)' ');
+					_header.put(_uri.getBytes("UTF-8")); // TODO check
+					_header.put(HttpTokens.CRLF);
+					_state = STATE_FLUSHING;
+					_noContent=true;
+					return;
+				}
+				else
+				{
+					_header.put(_method);
+					_header.put((byte)' ');
+					_header.put(_uri.getBytes("UTF-8")); // TODO check
+					_header.put((byte)' ');
+					_header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER);
+					_header.put(HttpTokens.CRLF);
+				}
+			}
+			else
+			{
+				// Responses
+				if (_version == HttpVersions.HTTP_0_9_ORDINAL)
+				{
+					_persistent = false;
+					_contentLength = HttpTokens.EOF_CONTENT;
+					_state = STATE_CONTENT;
+					return;
+				}
+				else
+				{
+					if (_persistent==null)
+						_persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL);
 
-                    // add response line
-                    Status status = _status<__status.length?__status[_status]:null;
+					// add response line
+					Status status = _status<__status.length?__status[_status]:null;
 
-                    if (status==null)
-                    {
-                        _header.put(HttpVersions.HTTP_1_1_BUFFER);
-                        _header.put((byte) ' ');
-                        _header.put((byte) ('0' + _status / 100));
-                        _header.put((byte) ('0' + (_status % 100) / 10));
-                        _header.put((byte) ('0' + (_status % 10)));
-                        _header.put((byte) ' ');
-                        if (_reason==null)
-                        {
-                            _header.put((byte) ('0' + _status / 100));
-                            _header.put((byte) ('0' + (_status % 100) / 10));
-                            _header.put((byte) ('0' + (_status % 10)));
-                        }
-                        else
-                            _header.put(_reason);
-                        _header.put(HttpTokens.CRLF);
-                    }
-                    else
-                    {
-                        if (_reason==null)
-                            _header.put(status._responseLine);
-                        else
-                        {
-                            _header.put(status._schemeCode);
-                            _header.put(_reason);
-                            _header.put(HttpTokens.CRLF);
-                        }
-                    }
+					if (status==null)
+					{
+						_header.put(HttpVersions.HTTP_1_1_BUFFER);
+						_header.put((byte) ' ');
+						_header.put((byte) ('0' + _status / 100));
+						_header.put((byte) ('0' + (_status % 100) / 10));
+						_header.put((byte) ('0' + (_status % 10)));
+						_header.put((byte) ' ');
+						if (_reason==null)
+						{
+							_header.put((byte) ('0' + _status / 100));
+							_header.put((byte) ('0' + (_status % 100) / 10));
+							_header.put((byte) ('0' + (_status % 10)));
+						}
+						else
+							_header.put(_reason);
+						_header.put(HttpTokens.CRLF);
+					}
+					else
+					{
+						if (_reason==null)
+							_header.put(status._responseLine);
+						else
+						{
+							_header.put(status._schemeCode);
+							_header.put(_reason);
+							_header.put(HttpTokens.CRLF);
+						}
+					}
 
-                    if (_status<200 && _status>=100 )
-                    {
-                        _noContent=true;
-                        _content=null;
-                        if (_buffer!=null)
-                            _buffer.clear();
-                        // end the header.
+					if (_status<200 && _status>=100 )
+					{
+						_noContent=true;
+						_content=null;
+						if (_buffer!=null)
+							_buffer.clear();
+						// end the header.
 
-                        if (_status!=101 )
-                        {
-                            _header.put(HttpTokens.CRLF);
-                            _state = STATE_CONTENT;
-                            return;
-                        }
-                    }
-                    else if (_status==204 || _status==304)
-                    {
-                        _noContent=true;
-                        _content=null;
-                        if (_buffer!=null)
-                            _buffer.clear();
-                    }
-                }
-            }
+						if (_status!=101 )
+						{
+							_header.put(HttpTokens.CRLF);
+							_state = STATE_CONTENT;
+							return;
+						}
+					}
+					else if (_status==204 || _status==304)
+					{
+						_noContent=true;
+						_content=null;
+						if (_buffer!=null)
+							_buffer.clear();
+					}
+				}
+			}
 
-            // Add headers
-            if (_status>=200 && _date!=null)
-            {
-                _header.put(HttpHeaders.DATE_BUFFER);
-                _header.put((byte)':');
-                _header.put((byte)' ');
-                _header.put(_date);
-                _header.put(CRLF);
-            }
+			// Add headers
+			if (_status>=200 && _date!=null)
+			{
+				_header.put(HttpHeaders.DATE_BUFFER);
+				_header.put((byte)':');
+				_header.put((byte)' ');
+				_header.put(_date);
+				_header.put(CRLF);
+			}
 
-            // key field values
-            HttpFields.Field content_length = null;
-            HttpFields.Field transfer_encoding = null;
-            boolean keep_alive = false;
-            boolean close=false;
-            boolean content_type=false;
-            StringBuilder connection = null;
+			// key field values
+			HttpFields.Field content_length = null;
+			HttpFields.Field transfer_encoding = null;
+			boolean keep_alive = false;
+			boolean close=false;
+			boolean content_type=false;
+			StringBuilder connection = null;
 
-            if (fields != null)
-            {
-                int s=fields.size();
-                for (int f=0;f<s;f++)
-                {
-                    HttpFields.Field field = fields.getField(f);
-                    if (field==null)
-                        continue;
+			if (fields != null)
+			{
+				int s=fields.size();
+				for (int f=0;f<s;f++)
+				{
+					HttpFields.Field field = fields.getField(f);
+					if (field==null)
+						continue;
 
-                    switch (field.getNameOrdinal())
-                    {
-                        case HttpHeaders.CONTENT_LENGTH_ORDINAL:
-                            content_length = field;
-                            _contentLength = field.getLongValue();
+					switch (field.getNameOrdinal())
+					{
+						case HttpHeaders.CONTENT_LENGTH_ORDINAL:
+							content_length = field;
+							_contentLength = field.getLongValue();
 
-                            if (_contentLength < _contentWritten || _last && _contentLength != _contentWritten)
-                                content_length = null;
+							if (_contentLength < _contentWritten || _last && _contentLength != _contentWritten)
+								content_length = null;
 
-                            // write the field to the header buffer
-                            field.putTo(_header);
-                            break;
+							// write the field to the header buffer
+							field.putTo(_header);
+							break;
 
-                        case HttpHeaders.CONTENT_TYPE_ORDINAL:
-                            if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
+						case HttpHeaders.CONTENT_TYPE_ORDINAL:
+							if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT;
 
-                            // write the field to the header buffer
-                            content_type=true;
-                            field.putTo(_header);
-                            break;
+							// write the field to the header buffer
+							content_type=true;
+							field.putTo(_header);
+							break;
 
-                        case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
-                            if (_version == HttpVersions.HTTP_1_1_ORDINAL)
-                                transfer_encoding = field;
-                            // Do NOT add yet!
-                            break;
+						case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
+							if (_version == HttpVersions.HTTP_1_1_ORDINAL)
+								transfer_encoding = field;
+							// Do NOT add yet!
+							break;
 
-                        case HttpHeaders.CONNECTION_ORDINAL:
-                            if (isRequest())
-                                field.putTo(_header);
+						case HttpHeaders.CONNECTION_ORDINAL:
+							if (isRequest())
+								field.putTo(_header);
 
-                            int connection_value = field.getValueOrdinal();
-                            switch (connection_value)
-                            {
-                                case -1:
-                                {
-                                    String[] values = field.getValue().split(",");
-                                    for  (int i=0;values!=null && i<values.length;i++)
-                                    {
-                                        CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
+							int connection_value = field.getValueOrdinal();
+							switch (connection_value)
+							{
+								case -1:
+								{
+									String[] values = field.getValue().split(",");
+									for  (int i=0;values!=null && i<values.length;i++)
+									{
+										CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim());
 
-                                        if (cb!=null)
-                                        {
-                                            switch(cb.getOrdinal())
-                                            {
-                                                case HttpHeaderValues.CLOSE_ORDINAL:
-                                                    close=true;
-                                                    if (isResponse())
-                                                        _persistent=false;
-                                                    keep_alive=false;
-                                                    if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
-                                                        _contentLength = HttpTokens.EOF_CONTENT;
-                                                    break;
+										if (cb!=null)
+										{
+											switch(cb.getOrdinal())
+											{
+												case HttpHeaderValues.CLOSE_ORDINAL:
+													close=true;
+													if (isResponse())
+														_persistent=false;
+													keep_alive=false;
+													if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
+														_contentLength = HttpTokens.EOF_CONTENT;
+													break;
 
-                                                case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
-                                                    if (_version == HttpVersions.HTTP_1_0_ORDINAL)
-                                                    {
-                                                        keep_alive = true;
-                                                        if (isResponse())
-                                                            _persistent = true;
-                                                    }
-                                                    break;
+												case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
+													if (_version == HttpVersions.HTTP_1_0_ORDINAL)
+													{
+														keep_alive = true;
+														if (isResponse())
+															_persistent = true;
+													}
+													break;
 
-                                                default:
-                                                    if (connection==null)
-                                                        connection=new StringBuilder();
-                                                    else
-                                                        connection.append(',');
-                                                    connection.append(values[i]);
-                                            }
-                                        }
-                                        else
-                                        {
-                                            if (connection==null)
-                                                connection=new StringBuilder();
-                                            else
-                                                connection.append(',');
-                                            connection.append(values[i]);
-                                        }
-                                    }
+												default:
+													if (connection==null)
+														connection=new StringBuilder();
+													else
+														connection.append(',');
+													connection.append(values[i]);
+											}
+										}
+										else
+										{
+											if (connection==null)
+												connection=new StringBuilder();
+											else
+												connection.append(',');
+											connection.append(values[i]);
+										}
+									}
 
-                                    break;
-                                }
-                                case HttpHeaderValues.UPGRADE_ORDINAL:
-                                {
-                                    // special case for websocket connection ordering
-                                    if (isResponse())
-                                    {
-                                        field.putTo(_header);
-                                        continue;
-                                    }
-                                }
-                                case HttpHeaderValues.CLOSE_ORDINAL:
-                                {
-                                    close=true;
-                                    if (isResponse())
-                                        _persistent=false;
-                                    if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
-                                        _contentLength = HttpTokens.EOF_CONTENT;
-                                    break;
-                                }
-                                case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
-                                {
-                                    if (_version == HttpVersions.HTTP_1_0_ORDINAL)
-                                    {
-                                        keep_alive = true;
-                                        if (isResponse())
-                                            _persistent=true;
-                                    }
-                                    break;
-                                }
-                                default:
-                                {
-                                    if (connection==null)
-                                        connection=new StringBuilder();
-                                    else
-                                        connection.append(',');
-                                    connection.append(field.getValue());
-                                }
-                            }
+									break;
+								}
+								case HttpHeaderValues.UPGRADE_ORDINAL:
+								{
+									// special case for websocket connection ordering
+									if (isResponse())
+									{
+										field.putTo(_header);
+										continue;
+									}
+								}
+								case HttpHeaderValues.CLOSE_ORDINAL:
+								{
+									close=true;
+									if (isResponse())
+										_persistent=false;
+									if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT)
+										_contentLength = HttpTokens.EOF_CONTENT;
+									break;
+								}
+								case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
+								{
+									if (_version == HttpVersions.HTTP_1_0_ORDINAL)
+									{
+										keep_alive = true;
+										if (isResponse())
+											_persistent=true;
+									}
+									break;
+								}
+								default:
+								{
+									if (connection==null)
+										connection=new StringBuilder();
+									else
+										connection.append(',');
+									connection.append(field.getValue());
+								}
+							}
 
-                            // Do NOT add yet!
-                            break;
+							// Do NOT add yet!
+							break;
 
-                        case HttpHeaders.SERVER_ORDINAL:
-                            if (getSendServerVersion())
-                            {
-                                has_server=true;
-                                field.putTo(_header);
-                            }
-                            break;
+						case HttpHeaders.SERVER_ORDINAL:
+							has_server=true;
+							field.putTo(_header);
+							break;
 
-                        default:
-                            // write the field to the header buffer
-                            field.putTo(_header);
-                    }
-                }
-            }
+						default:
+							// write the field to the header buffer
+							field.putTo(_header);
+					}
+				}
+			}
 
-            // Calculate how to end _content and connection, _content length and transfer encoding
-            // settings.
-            // From RFC 2616 4.4:
-            // 1. No body for 1xx, 204, 304 & HEAD response
-            // 2. Force _content-length?
-            // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk
-            // 4. Content-Length
-            // 5. multipart/byteranges
-            // 6. close
-            switch ((int) _contentLength)
-            {
-                case HttpTokens.UNKNOWN_CONTENT:
-                    // It may be that we have no _content, or perhaps _content just has not been
-                    // written yet?
+			// Calculate how to end _content and connection, _content length and transfer encoding
+			// settings.
+			// From RFC 2616 4.4:
+			// 1. No body for 1xx, 204, 304 & HEAD response
+			// 2. Force _content-length?
+			// 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk
+			// 4. Content-Length
+			// 5. multipart/byteranges
+			// 6. close
+			switch ((int) _contentLength)
+			{
+				case HttpTokens.UNKNOWN_CONTENT:
+					// It may be that we have no _content, or perhaps _content just has not been
+					// written yet?
 
-                    // Response known not to have a body
-                    if (_contentWritten == 0 && isResponse() && (_status < 200 || _status == 204 || _status == 304))
-                        _contentLength = HttpTokens.NO_CONTENT;
-                    else if (_last)
-                    {
-                        // we have seen all the _content there is
-                        _contentLength = _contentWritten;
-                        if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent)
-                        {
-                            // known length but not actually set.
-                            _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
-                            _header.put(HttpTokens.COLON);
-                            _header.put((byte) ' ');
-                            BufferUtil.putDecLong(_header, _contentLength);
-                            _header.put(HttpTokens.CRLF);
-                        }
-                    }
-                    else
-                    {
-                        // No idea, so we must assume that a body is coming
-                        _contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT;
-                        if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT)
-                        {
-                            _contentLength=HttpTokens.NO_CONTENT;
-                            _noContent=true;
-                        }
-                    }
-                    break;
+					// Response known not to have a body
+					if (_contentWritten == 0 && isResponse() && (_status < 200 || _status == 204 || _status == 304))
+						_contentLength = HttpTokens.NO_CONTENT;
+					else if (_last)
+					{
+						// we have seen all the _content there is
+						_contentLength = _contentWritten;
+						if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent)
+						{
+							// known length but not actually set.
+							_header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
+							_header.put(HttpTokens.COLON);
+							_header.put((byte) ' ');
+							BufferUtil.putDecLong(_header, _contentLength);
+							_header.put(HttpTokens.CRLF);
+						}
+					}
+					else
+					{
+						// No idea, so we must assume that a body is coming
+						_contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT;
+						if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT)
+						{
+							_contentLength=HttpTokens.NO_CONTENT;
+							_noContent=true;
+						}
+					}
+					break;
 
-                case HttpTokens.NO_CONTENT:
-                    if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304)
-                        _header.put(CONTENT_LENGTH_0);
-                    break;
+				case HttpTokens.NO_CONTENT:
+					if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304)
+						_header.put(CONTENT_LENGTH_0);
+					break;
 
-                case HttpTokens.EOF_CONTENT:
-                    _persistent = isRequest();
-                    break;
+				case HttpTokens.EOF_CONTENT:
+					_persistent = isRequest();
+					break;
 
-                case HttpTokens.CHUNKED_CONTENT:
-                    break;
+				case HttpTokens.CHUNKED_CONTENT:
+					break;
 
-                default:
-                    // TODO - maybe allow forced chunking by setting te ???
-                    break;
-            }
+				default:
+					// TODO - maybe allow forced chunking by setting te ???
+					break;
+			}
 
-            // Add transfer_encoding if needed
-            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
-            {
-                // try to use user supplied encoding as it may have other values.
-                if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal())
-                {
-                    String c = transfer_encoding.getValue();
-                    if (c.endsWith(HttpHeaderValues.CHUNKED))
-                        transfer_encoding.putTo(_header);
-                    else
-                        throw new IllegalArgumentException("BAD TE");
-                }
-                else
-                    _header.put(TRANSFER_ENCODING_CHUNKED);
-            }
+			// Add transfer_encoding if needed
+			if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+			{
+				// try to use user supplied encoding as it may have other values.
+				if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal())
+				{
+					String c = transfer_encoding.getValue();
+					if (c.endsWith(HttpHeaderValues.CHUNKED))
+						transfer_encoding.putTo(_header);
+					else
+						throw new IllegalArgumentException("BAD TE");
+				}
+				else
+					_header.put(TRANSFER_ENCODING_CHUNKED);
+			}
 
-            // Handle connection if need be
-            if (_contentLength==HttpTokens.EOF_CONTENT)
-            {
-                keep_alive=false;
-                _persistent=false;
-            }
+			// Handle connection if need be
+			if (_contentLength==HttpTokens.EOF_CONTENT)
+			{
+				keep_alive=false;
+				_persistent=false;
+			}
 
-            if (isResponse())
-            {
-                if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL))
-                {
-                    _header.put(CONNECTION_CLOSE);
-                    if (connection!=null)
-                    {
-                        _header.setPutIndex(_header.putIndex()-2);
-                        _header.put((byte)',');
-                        _header.put(connection.toString().getBytes());
-                        _header.put(CRLF);
-                    }
-                }
-                else if (keep_alive)
-                {
-                    _header.put(CONNECTION_KEEP_ALIVE);
-                    if (connection!=null)
-                    {
-                        _header.setPutIndex(_header.putIndex()-2);
-                        _header.put((byte)',');
-                        _header.put(connection.toString().getBytes());
-                        _header.put(CRLF);
-                    }
-                }
-                else if (connection!=null)
-                {
-                    _header.put(CONNECTION_);
-                    _header.put(connection.toString().getBytes());
-                    _header.put(CRLF);
-                }
-            }
+			if (isResponse())
+			{
+				if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL))
+				{
+					_header.put(CONNECTION_CLOSE);
+					if (connection!=null)
+					{
+						_header.setPutIndex(_header.putIndex()-2);
+						_header.put((byte)',');
+						_header.put(connection.toString().getBytes());
+						_header.put(CRLF);
+					}
+				}
+				else if (keep_alive)
+				{
+					_header.put(CONNECTION_KEEP_ALIVE);
+					if (connection!=null)
+					{
+						_header.setPutIndex(_header.putIndex()-2);
+						_header.put((byte)',');
+						_header.put(connection.toString().getBytes());
+						_header.put(CRLF);
+					}
+				}
+				else if (connection!=null)
+				{
+					_header.put(CONNECTION_);
+					_header.put(connection.toString().getBytes());
+					_header.put(CRLF);
+				}
+			}
 
-            if (!has_server && _status>199 && getSendServerVersion())
-                _header.put(SERVER);
+			if (!has_server && _status>199)
+				_header.put(SERVER);
 
-            // end the header.
-            _header.put(HttpTokens.CRLF);
-            _state = STATE_CONTENT;
+			// end the header.
+			_header.put(HttpTokens.CRLF);
+			_state = STATE_CONTENT;
 
-        }
-        catch(ArrayIndexOutOfBoundsException e)
-        {
-            throw new RuntimeException("Header>"+_header.capacity(),e);
-        }
-    }
+		}
+		catch(ArrayIndexOutOfBoundsException e)
+		{
+			throw new RuntimeException("Header>"+_header.capacity(),e);
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    /**
-     * Complete the message.
-     *
-     * @throws IOException
-     */
-    @Override
-    public void complete() throws IOException
-    {
-        if (_state == STATE_END)
-            return;
+	/* ------------------------------------------------------------ */
+	/**
+	 * Complete the message.
+	 *
+	 * @throws IOException
+	 */
+	@Override
+	public void complete() throws IOException
+	{
+		if (_state == STATE_END)
+			return;
 
-        super.complete();
+		super.complete();
 
-        if (_state < STATE_FLUSHING)
-        {
-            _state = STATE_FLUSHING;
-            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
-                _needEOC = true;
-        }
+		if (_state < STATE_FLUSHING)
+		{
+			_state = STATE_FLUSHING;
+			if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+				_needEOC = true;
+		}
 
-        flushBuffer();
-    }
+		flushBuffer();
+	}
 
-    /* ------------------------------------------------------------ */
-    @Override
-    public int flushBuffer() throws IOException
-    {
-        try
-        {
+	/* ------------------------------------------------------------ */
+	@Override
+	public int flushBuffer() throws IOException
+	{
+		try
+		{
 
-            if (_state == STATE_HEADER)
-                throw new IllegalStateException("State==HEADER");
+			if (_state == STATE_HEADER)
+				throw new IllegalStateException("State==HEADER");
 
-            prepareBuffers();
+			prepareBuffers();
 
-            if (_endp == null)
-            {
-                if (_needCRLF && _buffer!=null)
-                    _buffer.put(HttpTokens.CRLF);
-                if (_needEOC && _buffer!=null && !_head)
-                    _buffer.put(LAST_CHUNK);
-                _needCRLF=false;
-                _needEOC=false;
-                return 0;
-            }
+			if (_endp == null)
+			{
+				if (_needCRLF && _buffer!=null)
+					_buffer.put(HttpTokens.CRLF);
+				if (_needEOC && _buffer!=null && !_head)
+					_buffer.put(LAST_CHUNK);
+				_needCRLF=false;
+				_needEOC=false;
+				return 0;
+			}
 
-            int total= 0;
+			int total= 0;
 
-            int len = -1;
-            int to_flush = flushMask();
-            int last_flush;
+			int len = -1;
+			int to_flush = flushMask();
+			int last_flush;
 
-            do
-            {
-                last_flush=to_flush;
-                switch (to_flush)
-                {
-                    case 7:
-                        throw new IllegalStateException(); // should never happen!
-                    case 6:
-                        len = _endp.flush(_header, _buffer, null);
-                        break;
-                    case 5:
-                        len = _endp.flush(_header, _content, null);
-                        break;
-                    case 4:
-                        len = _endp.flush(_header);
-                        break;
-                    case 3:
-                        len = _endp.flush(_buffer, _content, null);
-                        break;
-                    case 2:
-                        len = _endp.flush(_buffer);
-                        break;
-                    case 1:
-                        len = _endp.flush(_content);
-                        break;
-                    case 0:
-                    {
-                        len=0;
-                        // Nothing more we can write now.
-                        if (_header != null)
-                            _header.clear();
+			do
+			{
+				last_flush=to_flush;
+				switch (to_flush)
+				{
+					case 7:
+						throw new IllegalStateException(); // should never happen!
+					case 6:
+						len = _endp.flush(_header, _buffer, null);
+						break;
+					case 5:
+						len = _endp.flush(_header, _content, null);
+						break;
+					case 4:
+						len = _endp.flush(_header);
+						break;
+					case 3:
+						len = _endp.flush(_buffer, _content, null);
+						break;
+					case 2:
+						len = _endp.flush(_buffer);
+						break;
+					case 1:
+						len = _endp.flush(_content);
+						break;
+					case 0:
+					{
+						len=0;
+						// Nothing more we can write now.
+						if (_header != null)
+							_header.clear();
 
-                        _bypass = false;
-                        _bufferChunked = false;
+						_bypass = false;
+						_bufferChunked = false;
 
-                        if (_buffer != null)
-                        {
-                            _buffer.clear();
-                            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
-                            {
-                                // reserve some space for the chunk header
-                                _buffer.setPutIndex(CHUNK_SPACE);
-                                _buffer.setGetIndex(CHUNK_SPACE);
+						if (_buffer != null)
+						{
+							_buffer.clear();
+							if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+							{
+								// reserve some space for the chunk header
+								_buffer.setPutIndex(CHUNK_SPACE);
+								_buffer.setGetIndex(CHUNK_SPACE);
 
-                                // Special case handling for small left over buffer from
-                                // an addContent that caused a buffer flush.
-                                if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
-                                {
-                                    _buffer.put(_content);
-                                    _content.clear();
-                                    _content=null;
-                                }
-                            }
-                        }
+								// Special case handling for small left over buffer from
+								// an addContent that caused a buffer flush.
+								if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
+								{
+									_buffer.put(_content);
+									_content.clear();
+									_content=null;
+								}
+							}
+						}
 
-                        // Are we completely finished for now?
-                        if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
-                        {
-                            if (_state == STATE_FLUSHING)
-                                _state = STATE_END;
+						// Are we completely finished for now?
+						if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
+						{
+							if (_state == STATE_FLUSHING)
+								_state = STATE_END;
 
-                            if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
-                                _endp.shutdownOutput();
-                        }
-                        else
-                            // Try to prepare more to write.
-                            prepareBuffers();
-                    }
+							if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
+								_endp.shutdownOutput();
+						}
+						else
+							// Try to prepare more to write.
+							prepareBuffers();
+					}
 
-                }
+				}
 
-                if (len > 0)
-                    total+=len;
+				if (len > 0)
+					total+=len;
 
-                to_flush = flushMask();
-            }
-            // loop while progress is being made (OR we have prepared some buffers that might make progress)
-            while (len>0 || (to_flush!=0 && last_flush==0));
+				to_flush = flushMask();
+			}
+			// loop while progress is being made (OR we have prepared some buffers that might make progress)
+			while (len>0 || (to_flush!=0 && last_flush==0));
 
-            return total;
-        }
-        catch (IOException e)
-        {
-            LOG.trace("",e);
-            throw (e instanceof EofException) ? e:new EofException(e);
-        }
-    }
+			return total;
+		}
+		catch (IOException e)
+		{
+			LOG.trace("",e);
+			throw (e instanceof EofException) ? e:new EofException(e);
+		}
+	}
 
-    /* ------------------------------------------------------------ */
-    private int flushMask()
-    {
-        return  ((_header != null && _header.length() > 0)?4:0)
-        | ((_buffer != null && _buffer.length() > 0)?2:0)
-        | ((_bypass && _content != null && _content.length() > 0)?1:0);
-    }
+	/* ------------------------------------------------------------ */
+	private int flushMask()
+	{
+		return  ((_header != null && _header.length() > 0)?4:0)
+		| ((_buffer != null && _buffer.length() > 0)?2:0)
+		| ((_bypass && _content != null && _content.length() > 0)?1:0);
+	}
 
-    /* ------------------------------------------------------------ */
-    private void prepareBuffers()
-    {
-        // if we are not flushing an existing chunk
-        if (!_bufferChunked)
-        {
-            // Refill buffer if possible
-            if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0)
-            {
-                int len = _buffer.put(_content);
-                _content.skip(len);
-                if (_content.length() == 0)
-                    _content = null;
-            }
+	/* ------------------------------------------------------------ */
+	private void prepareBuffers()
+	{
+		// if we are not flushing an existing chunk
+		if (!_bufferChunked)
+		{
+			// Refill buffer if possible
+			if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0)
+			{
+				int len = _buffer.put(_content);
+				_content.skip(len);
+				if (_content.length() == 0)
+					_content = null;
+			}
 
-            // Chunk buffer if need be
-            if (_contentLength == HttpTokens.CHUNKED_CONTENT)
-            {
-                if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null)
-                {
-                    // this is a bypass write
-                    int size = _content.length();
-                    _bufferChunked = true;
+			// Chunk buffer if need be
+			if (_contentLength == HttpTokens.CHUNKED_CONTENT)
+			{
+				if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null)
+				{
+					// this is a bypass write
+					int size = _content.length();
+					_bufferChunked = true;
 
-                    if (_header == null)
-                        _header = _buffers.getHeader();
+					if (_header == null)
+						_header = _buffers.getHeader();
 
-                    // if we need CRLF add this to header
-                    if (_needCRLF)
-                    {
-                        if (_header.length() > 0) throw new IllegalStateException("EOC");
-                        _header.put(HttpTokens.CRLF);
-                        _needCRLF = false;
-                    }
-                    // Add the chunk size to the header
-                    BufferUtil.putHexInt(_header, size);
-                    _header.put(HttpTokens.CRLF);
+					// if we need CRLF add this to header
+					if (_needCRLF)
+					{
+						if (_header.length() > 0) throw new IllegalStateException("EOC");
+						_header.put(HttpTokens.CRLF);
+						_needCRLF = false;
+					}
+					// Add the chunk size to the header
+					BufferUtil.putHexInt(_header, size);
+					_header.put(HttpTokens.CRLF);
 
-                    // Need a CRLF after the content
-                    _needCRLF=true;
-                }
-                else if (_buffer!=null)
-                {
-                    int size = _buffer.length();
-                    if (size > 0)
-                    {
-                        // Prepare a chunk!
-                        _bufferChunked = true;
+					// Need a CRLF after the content
+					_needCRLF=true;
+				}
+				else if (_buffer!=null)
+				{
+					int size = _buffer.length();
+					if (size > 0)
+					{
+						// Prepare a chunk!
+						_bufferChunked = true;
 
-                        // Did we leave space at the start of the buffer.
-                        //noinspection ConstantConditions
-                        if (_buffer.getIndex() == CHUNK_SPACE)
-                        {
-                            // Oh yes, goodie! let's use it then!
-                            _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
-                            _buffer.setGetIndex(_buffer.getIndex() - 2);
-                            BufferUtil.prependHexInt(_buffer, size);
+						// Did we leave space at the start of the buffer.
+						//noinspection ConstantConditions
+						if (_buffer.getIndex() == CHUNK_SPACE)
+						{
+							// Oh yes, goodie! let's use it then!
+							_buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
+							_buffer.setGetIndex(_buffer.getIndex() - 2);
+							BufferUtil.prependHexInt(_buffer, size);
 
-                            if (_needCRLF)
-                            {
-                                _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
-                                _buffer.setGetIndex(_buffer.getIndex() - 2);
-                                _needCRLF = false;
-                            }
-                        }
-                        else
-                        {
-                            // No space so lets use a header buffer.
-                            if (_header == null)
-                                _header = _buffers.getHeader();
+							if (_needCRLF)
+							{
+								_buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2);
+								_buffer.setGetIndex(_buffer.getIndex() - 2);
+								_needCRLF = false;
+							}
+						}
+						else
+						{
+							// No space so lets use a header buffer.
+							if (_header == null)
+								_header = _buffers.getHeader();
 
-                            if (_needCRLF)
-                            {
-                                if (_header.length() > 0) throw new IllegalStateException("EOC");
-                                _header.put(HttpTokens.CRLF);
-                                _needCRLF = false;
-                            }
-                            BufferUtil.putHexInt(_header, size);
-                            _header.put(HttpTokens.CRLF);
-                        }
+							if (_needCRLF)
+							{
+								if (_header.length() > 0) throw new IllegalStateException("EOC");
+								_header.put(HttpTokens.CRLF);
+								_needCRLF = false;
+							}
+							BufferUtil.putHexInt(_header, size);
+							_header.put(HttpTokens.CRLF);
+						}
 
-                        // Add end chunk trailer.
-                        if (_buffer.space() >= 2)
-                            _buffer.put(HttpTokens.CRLF);
-                        else
-                            _needCRLF = true;
-                    }
-                }
+						// Add end chunk trailer.
+						if (_buffer.space() >= 2)
+							_buffer.put(HttpTokens.CRLF);
+						else
+							_needCRLF = true;
+					}
+				}
 
-                // If we need EOC and everything written
-                if (_needEOC && (_content == null || _content.length() == 0))
-                {
-                    if (_header == null && _buffer == null)
-                        _header = _buffers.getHeader();
+				// If we need EOC and everything written
+				if (_needEOC && (_content == null || _content.length() == 0))
+				{
+					if (_header == null && _buffer == null)
+						_header = _buffers.getHeader();
 
-                    if (_needCRLF)
-                    {
-                        if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length)
-                        {
-                            _header.put(HttpTokens.CRLF);
-                            _needCRLF = false;
-                        }
-                        else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length)
-                        {
-                            _buffer.put(HttpTokens.CRLF);
-                            _needCRLF = false;
-                        }
-                    }
+					if (_needCRLF)
+					{
+						if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length)
+						{
+							_header.put(HttpTokens.CRLF);
+							_needCRLF = false;
+						}
+						else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length)
+						{
+							_buffer.put(HttpTokens.CRLF);
+							_needCRLF = false;
+						}
+					}
 
-                    if (!_needCRLF && _needEOC)
-                    {
-                        if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length)
-                        {
-                            if (!_head)
-                            {
-                                _header.put(LAST_CHUNK);
-                                _bufferChunked=true;
-                            }
-                            _needEOC = false;
-                        }
-                        else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length)
-                        {
-                            if (!_head)
-                            {
-                                _buffer.put(LAST_CHUNK);
-                                _bufferChunked=true;
-                            }
-                            _needEOC = false;
-                        }
-                    }
-                }
-            }
-        }
+					if (!_needCRLF && _needEOC)
+					{
+						if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length)
+						{
+							if (!_head)
+							{
+								_header.put(LAST_CHUNK);
+								_bufferChunked=true;
+							}
+							_needEOC = false;
+						}
+						else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length)
+						{
+							if (!_head)
+							{
+								_buffer.put(LAST_CHUNK);
+								_bufferChunked=true;
+							}
+							_needEOC = false;
+						}
+					}
+				}
+			}
+		}
 
-        if (_content != null && _content.length() == 0)
-            _content = null;
+		if (_content != null && _content.length() == 0)
+			_content = null;
 
-    }
+	}
 
-    public int getBytesBuffered()
-    {
-        return(_header==null?0:_header.length())+
-        (_buffer==null?0:_buffer.length())+
-        (_content==null?0:_content.length());
-    }
+	public int getBytesBuffered()
+	{
+		return(_header==null?0:_header.length())+
+		(_buffer==null?0:_buffer.length())+
+		(_content==null?0:_content.length());
+	}
 
-    public boolean isEmpty()
-    {
-        return (_header==null||_header.length()==0) &&
-        (_buffer==null||_buffer.length()==0) &&
-        (_content==null||_content.length()==0);
-    }
+	public boolean isEmpty()
+	{
+		return (_header==null||_header.length()==0) &&
+		(_buffer==null||_buffer.length()==0) &&
+		(_content==null||_content.length()==0);
+	}
 
-    @Override
-    public String toString()
-    {
-        Buffer header=_header;
-        Buffer buffer=_buffer;
-        Buffer content=_content;
-        return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
-                getClass().getSimpleName(),
-                _state,
-                header == null ? -1 : header.length(),
-                buffer == null ? -1 : buffer.length(),
-                content == null ? -1 : content.length());
-    }
+	@Override
+	public String toString()
+	{
+		Buffer header=_header;
+		Buffer buffer=_buffer;
+		Buffer content=_content;
+		return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
+				getClass().getSimpleName(),
+				_state,
+				header == null ? -1 : header.length(),
+				buffer == null ? -1 : buffer.length(),
+				content == null ? -1 : content.length());
+	}
 }
diff -r 2efdb98f3543 -r fef4392f4905 src/org/eclipse/jetty/server/AbstractHttpConnection.java
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Tue Oct 04 14:05:45 2016 -0600
+++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Tue Oct 04 14:36:51 2016 -0600
@@ -160,7 +160,6 @@
 		_request = new Request(this);
 		_response = new Response(this);
 		_generator = newHttpGenerator(ab.getResponseBuffers(), endpoint);
-		_generator.setSendServerVersion(server.getSendServerVersion());
 		_server = server;
 	}
 
@@ -178,7 +177,6 @@
 		_request = request;
 		_response = new Response(this);
 		_generator = generator;
-		_generator.setSendServerVersion(server.getSendServerVersion());
 		_server = server;
 	}
 
diff -r 2efdb98f3543 -r fef4392f4905 src/org/eclipse/jetty/server/Server.java
--- a/src/org/eclipse/jetty/server/Server.java	Tue Oct 04 14:05:45 2016 -0600
+++ b/src/org/eclipse/jetty/server/Server.java	Tue Oct 04 14:36:51 2016 -0600
@@ -64,7 +64,6 @@
 	private final AttributesMap _attributes = new AttributesMap();
 	public final ThreadPoolExecutor threadPool;
 	public final Connector connector;
-	private boolean _sendServerVersion = true; //send Server: header
 	private boolean _sendDateHeader = false; //send Date: header
 	private int _graceful=0;
 	private boolean _stopAtShutdown;
@@ -302,20 +301,6 @@
 	}
 
 	/* ------------------------------------------------------------ */
-
-	/* ------------------------------------------------------------ */
-	public void setSendServerVersion (boolean sendServerVersion)
-	{
-		_sendServerVersion = sendServerVersion;
-	}
-
-	/* ------------------------------------------------------------ */
-	public boolean getSendServerVersion()
-	{
-		return _sendServerVersion;
-	}
-
-	/* ------------------------------------------------------------ */
 	/**
 	 * @param sendDateHeader
 	 */