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