View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.http;
20  
21  import java.nio.ByteBuffer;
22  import java.nio.charset.StandardCharsets;
23  
24  import org.eclipse.jetty.http.HttpTokens.EndOfContent;
25  import org.eclipse.jetty.util.ArrayTernaryTrie;
26  import org.eclipse.jetty.util.BufferUtil;
27  import org.eclipse.jetty.util.StringUtil;
28  import org.eclipse.jetty.util.Trie;
29  import org.eclipse.jetty.util.TypeUtil;
30  import org.eclipse.jetty.util.log.Log;
31  import org.eclipse.jetty.util.log.Logger;
32  
33  
34  /* ------------------------------------------------------------ */
35  /** A Parser for HTTP 0.9, 1.0 and 1.1
36   * <p>
37   * The is parser parses HTTP client and server messages from buffers
38   * passed in the {@link #parseNext(ByteBuffer)} method.  The parsed
39   * elements of the HTTP message are passed as event calls to the 
40   * {@link HttpHandler} instance the parser is constructed with.
41   * If the passed handler is a {@link RequestHandler} then server side
42   * parsing is performed and if it is a {@link ResponseHandler}, then 
43   * client side parsing is done.
44   * </p>
45   * <p>
46   * The contract of the {@link HttpHandler} API is that if a call returns 
47   * true then the call to {@link #parseNext(ByteBuffer)} will return as 
48   * soon as possible also with a true response.  Typically this indicates
49   * that the parsing has reached a stage where the caller should process 
50   * the events accumulated by the handler.    It is the preferred calling
51   * style that handling such as calling a servlet to process a request, 
52   * should be done after a true return from {@link #parseNext(ByteBuffer)}
53   * rather than from within the scope of a call like 
54   * {@link RequestHandler#messageComplete()}
55   * </p>
56   * <p>
57   * For performance, the parse is heavily dependent on the 
58   * {@link Trie#getBest(ByteBuffer, int, int)} method to look ahead in a
59   * single pass for both the structure ( : and CRLF ) and semantic (which
60   * header and value) of a header.  Specifically the static {@link HttpField#CACHE}
61   * is used to lookup common combinations of headers and values 
62   * (eg. "Connection: close"), or just header names (eg. "Connection:" ).
63   * For headers who's value is not known statically (eg. Host, COOKIE) then a
64   * per parser dynamic Trie of {@link HttpFields} from previous parsed messages
65   * is used to help the parsing of subsequent messages.
66   * </p>
67   * <p>
68   * If the system property "org.eclipse.jetty.http.HttpParser.STRICT" is set to true,
69   * then the parser will strictly pass on the exact strings received for methods and header
70   * fields.  Otherwise a fast case insensitive string lookup is used that may alter the
71   * case of the method and/or headers
72   * </p>
73   */
74  public class HttpParser
75  {
76      public static final Logger LOG = Log.getLogger(HttpParser.class);
77      public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpParser.STRICT"); 
78      public final static int INITIAL_URI_LENGTH=256;
79  
80      // States
81      public enum State
82      {
83          START,
84          METHOD,
85          RESPONSE_VERSION,
86          SPACE1,
87          STATUS,
88          URI,
89          SPACE2,
90          REQUEST_VERSION,
91          REASON,
92          HEADER,
93          HEADER_IN_NAME,
94          HEADER_VALUE,
95          HEADER_IN_VALUE,
96          END,
97          EOF_CONTENT,
98          CONTENT,
99          CHUNKED_CONTENT,
100         CHUNK_SIZE,
101         CHUNK_PARAMS,
102         CHUNK,
103         CLOSED
104     };
105 
106     private final boolean DEBUG=LOG.isDebugEnabled();
107     private final HttpHandler<ByteBuffer> _handler;
108     private final RequestHandler<ByteBuffer> _requestHandler;
109     private final ResponseHandler<ByteBuffer> _responseHandler;
110     private final int _maxHeaderBytes;
111     private final boolean _strict;
112     private HttpField _field;
113     private HttpHeader _header;
114     private String _headerString;
115     private HttpHeaderValue _value;
116     private String _valueString;
117     private int _responseStatus;
118     private int _headerBytes;
119     private boolean _host;
120 
121     /* ------------------------------------------------------------------------------- */
122     private volatile State _state=State.START;
123     private HttpMethod _method;
124     private String _methodString;
125     private HttpVersion _version;
126     private ByteBuffer _uri=ByteBuffer.allocate(INITIAL_URI_LENGTH); // Tune?
127     private EndOfContent _endOfContent;
128     private long _contentLength;
129     private long _contentPosition;
130     private int _chunkLength;
131     private int _chunkPosition;
132     private boolean _headResponse;
133     private boolean _cr;
134     private ByteBuffer _contentChunk;
135     private Trie<HttpField> _connectionFields;
136 
137     private int _length;
138     private final StringBuilder _string=new StringBuilder();
139 
140     /* ------------------------------------------------------------------------------- */
141     public HttpParser(RequestHandler<ByteBuffer> handler)
142     {
143         this(handler,-1,__STRICT);
144     }
145 
146     /* ------------------------------------------------------------------------------- */
147     public HttpParser(ResponseHandler<ByteBuffer> handler)
148     {
149         this(handler,-1,__STRICT);
150     }
151 
152     /* ------------------------------------------------------------------------------- */
153     public HttpParser(RequestHandler<ByteBuffer> handler,int maxHeaderBytes)
154     {
155         this(handler,maxHeaderBytes,__STRICT);
156     }
157 
158     /* ------------------------------------------------------------------------------- */
159     public HttpParser(ResponseHandler<ByteBuffer> handler,int maxHeaderBytes)
160     {
161         this(handler,maxHeaderBytes,__STRICT);
162     }
163     
164     /* ------------------------------------------------------------------------------- */
165     public HttpParser(RequestHandler<ByteBuffer> handler,int maxHeaderBytes,boolean strict)
166     {
167         _handler=handler;
168         _requestHandler=handler;
169         _responseHandler=null;
170         _maxHeaderBytes=maxHeaderBytes;
171         _strict=strict;
172     }
173 
174     /* ------------------------------------------------------------------------------- */
175     public HttpParser(ResponseHandler<ByteBuffer> handler,int maxHeaderBytes,boolean strict)
176     {
177         _handler=handler;
178         _requestHandler=null;
179         _responseHandler=handler;
180         _maxHeaderBytes=maxHeaderBytes;
181         _strict=strict;
182     }
183 
184     /* ------------------------------------------------------------------------------- */
185     public long getContentLength()
186     {
187         return _contentLength;
188     }
189 
190     /* ------------------------------------------------------------ */
191     public long getContentRead()
192     {
193         return _contentPosition;
194     }
195 
196     /* ------------------------------------------------------------ */
197     /** Set if a HEAD response is expected
198      * @param head
199      */
200     public void setHeadResponse(boolean head)
201     {
202         _headResponse=head;
203     }
204 
205     /* ------------------------------------------------------------------------------- */
206     public State getState()
207     {
208         return _state;
209     }
210 
211     /* ------------------------------------------------------------------------------- */
212     public boolean inContentState()
213     {
214         return _state.ordinal() > State.END.ordinal();
215     }
216 
217     /* ------------------------------------------------------------------------------- */
218     public boolean inHeaderState()
219     {
220         return _state.ordinal() < State.END.ordinal();
221     }
222 
223     /* ------------------------------------------------------------------------------- */
224     public boolean isInContent()
225     {
226         return _state.ordinal()>State.END.ordinal() && _state.ordinal()<State.CLOSED.ordinal();
227     }
228 
229     /* ------------------------------------------------------------------------------- */
230     public boolean isChunking()
231     {
232         return _endOfContent==EndOfContent.CHUNKED_CONTENT;
233     }
234 
235     /* ------------------------------------------------------------ */
236     public boolean isStart()
237     {
238         return isState(State.START);
239     }
240 
241     /* ------------------------------------------------------------ */
242     public boolean isClosed()
243     {
244         return isState(State.CLOSED);
245     }
246 
247     /* ------------------------------------------------------------ */
248     public boolean isIdle()
249     {
250         return isState(State.START)||isState(State.END)||isState(State.CLOSED);
251     }
252 
253     /* ------------------------------------------------------------ */
254     public boolean isComplete()
255     {
256         return isState(State.END)||isState(State.CLOSED);
257     }
258 
259     /* ------------------------------------------------------------------------------- */
260     public boolean isState(State state)
261     {
262         return _state == state;
263     }
264 
265     /* ------------------------------------------------------------------------------- */
266     private static class BadMessage extends Error
267     {
268         private final int _code;
269         private final String _message;
270 
271         BadMessage()
272         {
273             this(400,null);
274         }
275         
276         BadMessage(int code)
277         {
278             this(code,null);
279         }
280         
281         BadMessage(String message)
282         {
283             this(400,message);
284         }
285         
286         BadMessage(int code,String message)
287         {
288             _code=code;
289             _message=message;
290         }
291         
292     }
293     
294     /* ------------------------------------------------------------------------------- */
295     private byte next(ByteBuffer buffer) 
296     {
297         byte ch=buffer.get();
298 
299         // If not a special character 
300         if (ch>=HttpTokens.SPACE || ch<0)
301         {
302             if (_cr)
303                 throw new BadMessage("Bad EOL");
304             
305             /*
306             if (ch>HttpTokens.SPACE)
307                 System.err.println("Next "+(char)ch);
308             else
309                 System.err.println("Next ["+ch+"]");*/
310             return ch;   
311         }
312             
313         
314         // Only a LF acceptable after CR
315         if (_cr)
316         {
317             _cr=false;
318             if (ch==HttpTokens.LINE_FEED)
319                 return ch;
320 
321             throw new BadMessage("Bad EOL");
322         }
323         
324         // If it is a CR
325         if (ch==HttpTokens.CARRIAGE_RETURN)
326         {
327             // Skip CR and look for a LF
328             if (buffer.hasRemaining())
329             {
330                 if(_maxHeaderBytes>0 && _state.ordinal()<State.END.ordinal())
331                     _headerBytes++;
332                 ch=buffer.get();
333                 if (ch==HttpTokens.LINE_FEED)
334                     return ch;
335 
336                 throw new BadMessage("Bad EOL");
337             }
338 
339             // Defer lookup of LF
340             _cr=true;
341             return 0;
342         }
343         
344         // Only LF or TAB acceptable special characters
345         if (ch!=HttpTokens.LINE_FEED && ch!=HttpTokens.TAB)
346             throw new BadMessage("Illegal character");
347         
348         /*
349         if (ch>HttpTokens.SPACE)
350             System.err.println("Next "+(char)ch);
351         else
352             System.err.println("Next ["+ch+"]");
353             */
354         return ch;
355     }
356     
357     /* ------------------------------------------------------------------------------- */
358     /* Quick lookahead for the start state looking for a request method or a HTTP version,
359      * otherwise skip white space until something else to parse.
360      */
361     private boolean quickStart(ByteBuffer buffer)
362     {
363         // Quick start look
364         while (_state==State.START && buffer.hasRemaining())
365         {
366             if (_requestHandler!=null)
367             {
368                 _method = HttpMethod.lookAheadGet(buffer);
369                 if (_method!=null)
370                 {
371                     _methodString = _method.asString();
372                     buffer.position(buffer.position()+_methodString.length()+1);
373                     setState(State.SPACE1);
374                     return false;
375                 }
376             }
377             else if (_responseHandler!=null)
378             {
379                 _version = HttpVersion.lookAheadGet(buffer);
380                 if (_version!=null)
381                 {
382                     buffer.position(buffer.position()+_version.asString().length()+1);
383                     setState(State.SPACE1);
384                     return false;
385                 }
386             }
387 
388             byte ch=next(buffer);
389             
390             if (ch > HttpTokens.SPACE)
391             {
392                 _string.setLength(0);
393                 _string.append((char)ch);
394                 setState(_requestHandler!=null?State.METHOD:State.RESPONSE_VERSION);
395                 return false;
396             }
397         }
398         return false;
399     }
400 
401     /* ------------------------------------------------------------------------------- */
402     private void setString(String s)
403     {
404         _string.setLength(0);
405         _string.append(s);
406         _length=s.length();
407     }
408     
409     /* ------------------------------------------------------------------------------- */
410     private String takeString()
411     {
412         _string.setLength(_length);
413         String s =_string.toString();
414         _string.setLength(0);
415         _length=-1;
416         return s;
417     }
418 
419     /* ------------------------------------------------------------------------------- */
420     /* Parse a request or response line
421      */
422     private boolean parseLine(ByteBuffer buffer)
423     {
424         boolean return_from_parse=false;
425 
426         // Process headers
427         while (_state.ordinal()<State.HEADER.ordinal() && buffer.hasRemaining() && !return_from_parse)
428         {
429             // process each character
430             byte ch=next(buffer);
431             if (ch==0)
432                 continue;
433 
434             if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
435             {
436                 if (_state==State.URI)
437                 {
438                     LOG.warn("URI is too large >"+_maxHeaderBytes);
439                     throw new BadMessage(HttpStatus.REQUEST_URI_TOO_LONG_414);
440                 }
441                 else
442                 {
443                     if (_requestHandler!=null)
444                         LOG.warn("request is too large >"+_maxHeaderBytes);
445                     else
446                         LOG.warn("response is too large >"+_maxHeaderBytes);
447                     throw new BadMessage(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
448                 }
449             }
450 
451             switch (_state)
452             {
453                 case METHOD:
454                     if (ch == HttpTokens.SPACE)
455                     {
456                         _length=_string.length();
457                         _methodString=takeString();
458                         HttpMethod method=HttpMethod.CACHE.get(_methodString);
459                         if (method!=null && !_strict)
460                             _methodString=method.asString();
461                         setState(State.SPACE1);
462                     }
463                     else if (ch<HttpTokens.SPACE)
464                         throw new BadMessage(ch<0?"Illegal character":"No URI");
465                     else
466                         _string.append((char)ch);
467                     break;
468 
469                 case RESPONSE_VERSION:
470                     if (ch == HttpTokens.SPACE)
471                     {
472                         _length=_string.length();
473                         String version=takeString();
474                         _version=HttpVersion.CACHE.get(version);
475                         if (_version==null)
476                         {
477                             throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Unknown Version");
478                         }
479                         setState(State.SPACE1);
480                     }
481                     else if (ch < HttpTokens.SPACE)
482                         throw new BadMessage(ch<0?"Illegal character":"No Status");
483                     else
484                         _string.append((char)ch);
485                     break;
486 
487                 case SPACE1:
488                     if (ch > HttpTokens.SPACE)
489                     {
490                         if (_responseHandler!=null)
491                         {
492                             setState(State.STATUS);
493                             _responseStatus=ch-'0';
494                         }
495                         else
496                         {
497                             _uri.clear();
498                             setState(State.URI);
499                             // quick scan for space or EoBuffer
500                             if (buffer.hasArray())
501                             {
502                                 byte[] array=buffer.array();
503                                 int p=buffer.arrayOffset()+buffer.position();
504                                 int l=buffer.arrayOffset()+buffer.limit();
505                                 int i=p;
506                                 while (i<l && array[i]>HttpTokens.SPACE)
507                                     i++;
508 
509                                 int len=i-p;
510                                 _headerBytes+=len;
511                                 
512                                 if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
513                                 {
514                                     LOG.warn("URI is too large >"+_maxHeaderBytes);
515                                     throw new BadMessage(HttpStatus.REQUEST_URI_TOO_LONG_414);
516                                 }
517                                 if (_uri.remaining()<=len)
518                                 {
519                                     ByteBuffer uri = ByteBuffer.allocate(_uri.capacity()+2*len);
520                                     _uri.flip();
521                                     uri.put(_uri);
522                                     _uri=uri;
523                                 }
524                                 _uri.put(array,p-1,len+1);
525                                 buffer.position(i-buffer.arrayOffset());
526                             }
527                             else
528                                 _uri.put(ch);
529                         }
530                     }
531                     else if (ch < HttpTokens.SPACE)
532                         throw new BadMessage(HttpStatus.BAD_REQUEST_400,_requestHandler!=null?"No URI":"No Status");
533                     break;
534 
535                 case STATUS:
536                     if (ch == HttpTokens.SPACE)
537                     {
538                         setState(State.SPACE2);
539                     }
540                     else if (ch>='0' && ch<='9')
541                     {
542                         _responseStatus=_responseStatus*10+(ch-'0');
543                     }
544                     else if (ch < HttpTokens.SPACE && ch>=0)
545                     {
546                         return_from_parse=_responseHandler.startResponse(_version, _responseStatus, null)||return_from_parse;
547                         setState(State.HEADER);
548                     }
549                     else
550                     {
551                         throw new BadMessage();
552                     }
553                     break;
554 
555                 case URI:
556                     if (ch == HttpTokens.SPACE)
557                     {
558                         setState(State.SPACE2);
559                     }
560                     else if (ch < HttpTokens.SPACE && ch>=0)
561                     {
562                         // HTTP/0.9
563                         _uri.flip();
564                         return_from_parse=_requestHandler.startRequest(_method,_methodString,_uri,null)||return_from_parse;
565                         setState(State.END);
566                         BufferUtil.clear(buffer);
567                         return_from_parse=_handler.headerComplete()||return_from_parse;
568                         return_from_parse=_handler.messageComplete()||return_from_parse;
569                     }
570                     else
571                     {
572                         if (!_uri.hasRemaining())
573                         {
574                             ByteBuffer uri = ByteBuffer.allocate(_uri.capacity()*2);
575                             _uri.flip();
576                             uri.put(_uri);
577                             _uri=uri;
578                         }
579                         _uri.put(ch);
580                     }
581                     break;
582 
583                 case SPACE2:
584                     if (ch > HttpTokens.SPACE)
585                     {
586                         _string.setLength(0);
587                         _string.append((char)ch);
588                         if (_responseHandler!=null)
589                         {
590                             _length=1;
591                             setState(State.REASON);
592                         }
593                         else
594                         {
595                             setState(State.REQUEST_VERSION);
596 
597                             // try quick look ahead for HTTP Version
598                             if (buffer.position()>0 && buffer.hasArray())
599                             {
600                                 HttpVersion version=HttpVersion.lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position()-1,buffer.arrayOffset()+buffer.limit());
601                                 if (version!=null) 
602                                 {
603                                     int pos = buffer.position()+version.asString().length()-1;
604                                     if (pos<buffer.limit())
605                                     {
606                                         byte n=buffer.get(pos);
607                                         if (n==HttpTokens.CARRIAGE_RETURN)
608                                         {
609                                             _cr=true;
610                                             _version=version;
611                                             _string.setLength(0);
612                                             buffer.position(pos+1);
613                                         }
614                                         else if (n==HttpTokens.LINE_FEED)
615                                         {
616                                             _version=version;
617                                             _string.setLength(0);
618                                             buffer.position(pos);
619                                         }
620                                     }
621                                 }
622                             }
623                         }
624                     }
625                     else if (ch == HttpTokens.LINE_FEED)
626                     {
627                         if (_responseHandler!=null)
628                         {
629                             return_from_parse=_responseHandler.startResponse(_version, _responseStatus, null)||return_from_parse;
630                             setState(State.HEADER);
631                         }
632                         else
633                         {
634                             // HTTP/0.9
635                             _uri.flip();
636                             return_from_parse=_requestHandler.startRequest(_method,_methodString,_uri, null)||return_from_parse;
637                             setState(State.END);
638                             BufferUtil.clear(buffer);
639                             return_from_parse=_handler.headerComplete()||return_from_parse;
640                             return_from_parse=_handler.messageComplete()||return_from_parse;
641                         }
642                     }
643                     else if (ch<HttpTokens.SPACE)
644                         throw new BadMessage();
645                     break;
646 
647                 case REQUEST_VERSION:
648                     if (ch == HttpTokens.LINE_FEED)
649                     {
650                         if (_version==null)
651                         {
652                             _length=_string.length();
653                             _version=HttpVersion.CACHE.get(takeString());
654                         }
655                         if (_version==null)
656                         {
657                             throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Unknown Version");
658                         }
659                         
660                         // Should we try to cache header fields?
661                         if (_connectionFields==null && _version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
662                         {
663                             int header_cache = _handler.getHeaderCacheSize();
664                             if (header_cache>0)
665                                 _connectionFields=new ArrayTernaryTrie<>(header_cache);
666                         }
667 
668                         setState(State.HEADER);
669                         _uri.flip();
670                         return_from_parse=_requestHandler.startRequest(_method,_methodString,_uri, _version)||return_from_parse;
671                         continue;
672                     }
673                     else if (ch>HttpTokens.SPACE)
674                         _string.append((char)ch);
675                     else
676                         throw new BadMessage();
677 
678                     break;
679 
680                 case REASON:
681                     if (ch == HttpTokens.LINE_FEED)
682                     {
683                         String reason=takeString();
684 
685                         setState(State.HEADER);
686                         return_from_parse=_responseHandler.startResponse(_version, _responseStatus, reason)||return_from_parse;
687                         continue;
688                     }
689                     else if (ch>=HttpTokens.SPACE)
690                     {
691                         _string.append((char)ch);
692                         if (ch!=' '&&ch!='\t')
693                             _length=_string.length();
694                     }
695                     else
696                         throw new BadMessage();
697                     break;
698 
699                 default:
700                     throw new IllegalStateException(_state.toString());
701 
702             }
703         }
704 
705         return return_from_parse;
706     }
707 
708     private boolean handleKnownHeaders(ByteBuffer buffer)
709     {
710         boolean add_to_connection_trie=false;
711         switch (_header)
712         {
713             case CONTENT_LENGTH:
714                 if (_endOfContent != EndOfContent.CHUNKED_CONTENT)
715                 {
716                     try
717                     {
718                         _contentLength=Long.parseLong(_valueString);
719                     }
720                     catch(NumberFormatException e)
721                     {
722                         LOG.ignore(e);
723                         throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Content-Length");
724                     }
725                     if (_contentLength <= 0)
726                         _endOfContent=EndOfContent.NO_CONTENT;
727                     else
728                         _endOfContent=EndOfContent.CONTENT_LENGTH;
729                 }
730                 break;
731 
732             case TRANSFER_ENCODING:
733                 if (_value==HttpHeaderValue.CHUNKED)
734                     _endOfContent=EndOfContent.CHUNKED_CONTENT;
735                 else
736                 {
737                     if (_valueString.endsWith(HttpHeaderValue.CHUNKED.toString()))
738                         _endOfContent=EndOfContent.CHUNKED_CONTENT;
739                     else if (_valueString.indexOf(HttpHeaderValue.CHUNKED.toString()) >= 0)
740                     {
741                         throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad chunking");
742                     }
743                 }
744                 break;
745 
746             case HOST:
747                 add_to_connection_trie=_connectionFields!=null && _field==null;
748                 _host=true;
749                 String host=_valueString;
750                 int port=0;
751                 if (host==null || host.length()==0)
752                 {
753                     throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header");
754                 }
755 
756                 int len=host.length();
757                 loop: for (int i = len; i-- > 0;)
758                 {
759                     char c2 = (char)(0xff & host.charAt(i));
760                     switch (c2)
761                     {
762                         case ']':
763                             break loop;
764 
765                         case ':':
766                             try
767                             {
768                                 len=i;
769                                 port = StringUtil.toInt(host.substring(i+1));
770                             }
771                             catch (NumberFormatException e)
772                             {
773                                 if (DEBUG)
774                                     LOG.debug(e);
775                                 throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header");
776                             }
777                             break loop;
778                     }
779                 }
780                 if (host.charAt(0)=='[')
781                 {
782                     if (host.charAt(len-1)!=']') 
783                     {
784                         throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad IPv6 Host header");
785                     }
786                     host = host.substring(1,len-1);
787                 }
788                 else if (len!=host.length())
789                     host = host.substring(0,len);
790                 
791                 if (_requestHandler!=null)
792                     _requestHandler.parsedHostHeader(host,port);
793                 
794               break;
795               
796             case CONNECTION:
797                 // Don't cache if not persistent
798                 if (_valueString!=null && _valueString.indexOf("close")>=0)
799                     _connectionFields=null;
800                 break;
801 
802             case AUTHORIZATION:
803             case ACCEPT:
804             case ACCEPT_CHARSET:
805             case ACCEPT_ENCODING:
806             case ACCEPT_LANGUAGE:
807             case COOKIE:
808             case CACHE_CONTROL:
809             case USER_AGENT:
810                 add_to_connection_trie=_connectionFields!=null && _field==null;
811                 break;
812                 
813             default: break;
814         }
815     
816         if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null)
817         {
818             _field=new HttpField.CachedHttpField(_header,_valueString);
819             _connectionFields.put(_field);
820         }
821         
822         return false;
823     }
824     
825     
826     /* ------------------------------------------------------------------------------- */
827     /*
828      * Parse the message headers and return true if the handler has signaled for a return
829      */
830     private boolean parseHeaders(ByteBuffer buffer)
831     {
832         boolean return_from_parse=false;
833 
834         // Process headers
835         while (_state.ordinal()<State.END.ordinal() && buffer.hasRemaining() && !return_from_parse)
836         {
837             // process each character
838             byte ch=next(buffer);
839             if (ch==0)
840                 continue;
841             
842             if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
843             {
844                 LOG.warn("Header is too large >"+_maxHeaderBytes);
845                 throw new BadMessage(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
846             }
847 
848             switch (_state)
849             {
850                 case HEADER:
851                     switch(ch)
852                     {
853                         case HttpTokens.COLON:
854                         case HttpTokens.SPACE:
855                         case HttpTokens.TAB:
856                         {
857                             // header value without name - continuation?
858                             if (_valueString==null)
859                             {
860                                 _string.setLength(0);
861                                 _length=0;
862                             }
863                             else
864                             {
865                                 setString(_valueString);
866                                 _string.append(' ');
867                                 _length++;
868                                 _valueString=null;
869                             }
870                             setState(State.HEADER_VALUE);
871                             break;
872                         }
873 
874                         default:
875                         {
876                             // handler last header if any.  Delayed to here just in case there was a continuation line (above)
877                             if (_headerString!=null || _valueString!=null)
878                             {
879                                 // Handle known headers
880                                 if (_header!=null && handleKnownHeaders(buffer))
881                                 {
882                                     _headerString=_valueString=null;
883                                     _header=null;
884                                     _value=null;
885                                     _field=null;
886                                     return true;
887                                 }
888                                 return_from_parse=_handler.parsedHeader(_field!=null?_field:new HttpField(_header,_headerString,_valueString))||return_from_parse;
889                             }
890                             _headerString=_valueString=null;
891                             _header=null;
892                             _value=null;
893                             _field=null;
894 
895                             // now handle the ch
896                             if (ch == HttpTokens.LINE_FEED)
897                             {
898                                 _contentPosition=0;
899 
900                                 // End of headers!
901 
902                                 // Was there a required host header?
903                                 if (!_host && _version!=HttpVersion.HTTP_1_0 && _requestHandler!=null)
904                                 {
905                                     throw new BadMessage(HttpStatus.BAD_REQUEST_400,"No Host");
906                                 }
907 
908                                 // is it a response that cannot have a body?
909                                 if (_responseHandler !=null  && // response  
910                                     (_responseStatus == 304  || // not-modified response
911                                     _responseStatus == 204 || // no-content response
912                                     _responseStatus < 200)) // 1xx response
913                                     _endOfContent=EndOfContent.NO_CONTENT; // ignore any other headers set
914                                 
915                                 // else if we don't know framing
916                                 else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
917                                 {
918                                     if (_responseStatus == 0  // request
919                                             || _responseStatus == 304 // not-modified response
920                                             || _responseStatus == 204 // no-content response
921                                             || _responseStatus < 200) // 1xx response
922                                         _endOfContent=EndOfContent.NO_CONTENT;
923                                     else
924                                         _endOfContent=EndOfContent.EOF_CONTENT;
925                                 }
926 
927                                 // How is the message ended?
928                                 switch (_endOfContent)
929                                 {
930                                     case EOF_CONTENT:
931                                         setState(State.EOF_CONTENT);
932                                         return_from_parse=_handler.headerComplete()||return_from_parse;
933                                         break;
934 
935                                     case CHUNKED_CONTENT:
936                                         setState(State.CHUNKED_CONTENT);
937                                         return_from_parse=_handler.headerComplete()||return_from_parse;
938                                         break;
939 
940                                     case NO_CONTENT:
941                                         return_from_parse=_handler.headerComplete()||return_from_parse;
942                                         setState(State.END);
943                                         return_from_parse=_handler.messageComplete()||return_from_parse;
944                                         break;
945 
946                                     default:
947                                         setState(State.CONTENT);
948                                         return_from_parse=_handler.headerComplete()||return_from_parse;
949                                         break;
950                                 }
951                             }
952                             else if (ch<=HttpTokens.SPACE)
953                                 throw new BadMessage();
954                             else
955                             {
956                                 if (buffer.hasRemaining())
957                                 {
958                                     // Try a look ahead for the known header name and value.
959                                     HttpField field=_connectionFields==null?null:_connectionFields.getBest(buffer,-1,buffer.remaining());
960                                     if (field==null)
961                                         field=HttpField.CACHE.getBest(buffer,-1,buffer.remaining());
962                                         
963                                     if (field!=null)
964                                     {
965                                         final String n;
966                                         final String v;
967 
968                                         if (_strict)
969                                         {
970                                             // Have to get the fields exactly from the buffer to match case
971                                             String fn=field.getName();
972                                             String fv=field.getValue();
973                                             n=BufferUtil.toString(buffer,buffer.position()-1,fn.length(),StandardCharsets.US_ASCII);
974                                             if (fv==null)
975                                                 v=null;
976                                             else
977                                             {
978                                                 v=BufferUtil.toString(buffer,buffer.position()+fn.length()+1,fv.length(),StandardCharsets.ISO_8859_1);
979                                                 field=new HttpField(field.getHeader(),n,v);
980                                             }
981                                         }
982                                         else
983                                         {
984                                             n=field.getName();
985                                             v=field.getValue(); 
986                                         }
987                                         
988                                         _header=field.getHeader();
989                                         _headerString=n;
990          
991                                         if (v==null)
992                                         {
993                                             // Header only
994                                             setState(State.HEADER_VALUE);
995                                             _string.setLength(0);
996                                             _length=0;
997                                             buffer.position(buffer.position()+n.length()+1);
998                                             break;
999                                         }
1000                                         else
1001                                         {
1002                                             // Header and value
1003                                             int pos=buffer.position()+n.length()+v.length()+1;
1004                                             byte b=buffer.get(pos);
1005 
1006                                             if (b==HttpTokens.CARRIAGE_RETURN || b==HttpTokens.LINE_FEED)
1007                                             {                     
1008                                                 _field=field;
1009                                                 _valueString=v;
1010                                                 setState(State.HEADER_IN_VALUE);
1011 
1012                                                 if (b==HttpTokens.CARRIAGE_RETURN)
1013                                                 {
1014                                                     _cr=true;
1015                                                     buffer.position(pos+1);
1016                                                 }
1017                                                 else
1018                                                     buffer.position(pos);
1019                                                 break;
1020                                             }
1021                                             else
1022                                             {
1023                                                 setState(State.HEADER_IN_VALUE);
1024                                                 setString(v);
1025                                                 buffer.position(pos);
1026                                                 break;
1027                                             }
1028                                         }
1029                                     }
1030                                 }
1031 
1032                                 // New header
1033                                 setState(State.HEADER_IN_NAME);
1034                                 _string.setLength(0);
1035                                 _string.append((char)ch);
1036                                 _length=1;
1037                             }
1038                         }
1039                     }
1040                     break;
1041 
1042                 case HEADER_IN_NAME:
1043                     if (ch==HttpTokens.COLON || ch==HttpTokens.LINE_FEED)
1044                     {
1045                         if (_headerString==null)
1046                         {
1047                             _headerString=takeString();
1048                             _header=HttpHeader.CACHE.get(_headerString);
1049                         }
1050                         _length=-1;
1051 
1052                         setState(ch==HttpTokens.LINE_FEED?State.HEADER:State.HEADER_VALUE);
1053                         break;
1054                     }
1055                     
1056                     if (ch>=HttpTokens.SPACE || ch==HttpTokens.TAB)
1057                     {
1058                         if (_header!=null)
1059                         {
1060                             setString(_header.asString());
1061                             _header=null;
1062                             _headerString=null;
1063                         }
1064 
1065                         _string.append((char)ch);
1066                         if (ch>HttpTokens.SPACE)
1067                             _length=_string.length();
1068                         break;
1069                     }
1070                      
1071                     throw new BadMessage("Illegal character");
1072 
1073                 case HEADER_VALUE:
1074                     if (ch>HttpTokens.SPACE || ch<0)
1075                     {
1076                         _string.append((char)(0xff&ch));
1077                         _length=_string.length();
1078                         setState(State.HEADER_IN_VALUE);
1079                         break;
1080                     }
1081                     
1082                     if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB)
1083                         break;
1084                     
1085                     if (ch==HttpTokens.LINE_FEED)
1086                     {
1087                         if (_length > 0)
1088                         {
1089                             _value=null;
1090                             _valueString=(_valueString==null)?takeString():(_valueString+" "+takeString());
1091                         }
1092                         setState(State.HEADER);
1093                         break; 
1094                     }
1095 
1096                     throw new BadMessage("Illegal character");
1097 
1098                 case HEADER_IN_VALUE:
1099                     if (ch>=HttpTokens.SPACE || ch<0)
1100                     {
1101                         if (_valueString!=null)
1102                         {
1103                             setString(_valueString);
1104                             _valueString=null;
1105                             _field=null;
1106                         }
1107                         _string.append((char)(0xff&ch));
1108                         if (ch>HttpTokens.SPACE || ch<0)
1109                             _length=_string.length();
1110                         break;
1111                     }
1112                     
1113                     if (ch==HttpTokens.LINE_FEED)
1114                     {
1115                         if (_length > 0)
1116                         {
1117                             _value=null;
1118                             _valueString=takeString();
1119                             _length=-1;
1120                         }
1121                         setState(State.HEADER);
1122                         break;
1123                     }
1124                     throw new BadMessage("Illegal character");
1125                     
1126                 default:
1127                     throw new IllegalStateException(_state.toString());
1128 
1129             }
1130         }
1131 
1132         return return_from_parse;
1133     }
1134 
1135     /* ------------------------------------------------------------------------------- */
1136     /**
1137      * Parse until next Event.
1138      * @return True if an {@link RequestHandler} method was called and it returned true;
1139      */
1140     public boolean parseNext(ByteBuffer buffer)
1141     {
1142         try
1143         {
1144             // handle initial state
1145             switch(_state)
1146             {
1147                 case START:
1148                     _version=null;
1149                     _method=null;
1150                     _methodString=null;
1151                     _endOfContent=EndOfContent.UNKNOWN_CONTENT;
1152                     _header=null;
1153                     if(quickStart(buffer))
1154                         return true;
1155                     break;
1156 
1157                 case CONTENT:
1158                     if (_contentPosition==_contentLength)
1159                     {
1160                         setState(State.END);
1161                         if(_handler.messageComplete())
1162                             return true;
1163                     }
1164                     break;
1165 
1166                 case END:
1167                     // eat white space
1168                     while (buffer.remaining()>0 && buffer.get(buffer.position())<=HttpTokens.SPACE)
1169                         buffer.get();
1170                     return false;
1171 
1172                 case CLOSED:
1173                     if (BufferUtil.hasContent(buffer))
1174                     {
1175                         // Just ignore data when closed
1176                         _headerBytes+=buffer.remaining();
1177                         BufferUtil.clear(buffer);
1178                         if (_headerBytes>_maxHeaderBytes)
1179                         {
1180                             // Don't want to waste time reading data of a closed request
1181                             throw new IllegalStateException("too much data after closed");
1182                         }
1183                     }
1184                     return false;
1185                 default: break;
1186     
1187             }
1188 
1189             // Request/response line
1190             if (_state.ordinal()<State.HEADER.ordinal())
1191                 if (parseLine(buffer))
1192                     return true;
1193 
1194             if (_state.ordinal()<State.END.ordinal())
1195                 if (parseHeaders(buffer))
1196                     return true;
1197 
1198             // Handle HEAD response
1199             if (_responseStatus>0 && _headResponse)
1200             {
1201                 setState(State.END);
1202                 if (_handler.messageComplete())
1203                     return true;
1204             }
1205 
1206 
1207             // Handle _content
1208             byte ch;
1209             while (_state.ordinal() > State.END.ordinal() && buffer.hasRemaining())
1210             {
1211                 switch (_state)
1212                 {
1213                     case EOF_CONTENT:
1214                         _contentChunk=buffer.asReadOnlyBuffer();
1215                         _contentPosition += _contentChunk.remaining();
1216                         buffer.position(buffer.position()+_contentChunk.remaining());
1217                         if (_handler.content(_contentChunk))
1218                             return true;
1219                         break;
1220 
1221                     case CONTENT:
1222                     {
1223                         long remaining=_contentLength - _contentPosition;
1224                         if (remaining == 0)
1225                         {
1226                             setState(State.END);
1227                             if (_handler.messageComplete())
1228                                 return true;
1229                         }
1230                         else
1231                         {
1232                             _contentChunk=buffer.asReadOnlyBuffer();
1233 
1234                             // limit content by expected size
1235                             if (_contentChunk.remaining() > remaining)
1236                             {
1237                                 // We can cast remaining to an int as we know that it is smaller than
1238                                 // or equal to length which is already an int.
1239                                 _contentChunk.limit(_contentChunk.position()+(int)remaining);
1240                             }
1241 
1242                             _contentPosition += _contentChunk.remaining();
1243                             buffer.position(buffer.position()+_contentChunk.remaining());
1244 
1245                             if (_handler.content(_contentChunk))
1246                                 return true;
1247 
1248                             if(_contentPosition == _contentLength)
1249                             {
1250                                 setState(State.END);
1251                                 if (_handler.messageComplete())
1252                                     return true;
1253                             }
1254                         }
1255                         break;
1256                     }
1257 
1258                     case CHUNKED_CONTENT:
1259                     {
1260                         ch=next(buffer);
1261                         if (ch>HttpTokens.SPACE)
1262                         {
1263                             _chunkLength=TypeUtil.convertHexDigit(ch);
1264                             _chunkPosition=0;
1265                             setState(State.CHUNK_SIZE);
1266                         }
1267                         
1268                         break;
1269                     }
1270 
1271                     case CHUNK_SIZE:
1272                     {
1273                         ch=next(buffer);
1274                         if (ch == HttpTokens.LINE_FEED)
1275                         {
1276                             if (_chunkLength == 0)
1277                             {
1278                                 setState(State.END);
1279                                 if (_handler.messageComplete())
1280                                     return true;
1281                             }
1282                             else
1283                                 setState(State.CHUNK);
1284                         }
1285                         else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON)
1286                             setState(State.CHUNK_PARAMS);
1287                         else 
1288                             _chunkLength=_chunkLength * 16 + TypeUtil.convertHexDigit(ch);
1289                         break;
1290                     }
1291 
1292                     case CHUNK_PARAMS:
1293                     {
1294                         ch=next(buffer);
1295                         if (ch == HttpTokens.LINE_FEED)
1296                         {
1297                             if (_chunkLength == 0)
1298                             {
1299                                 setState(State.END);
1300                                 if (_handler.messageComplete())
1301                                     return true;
1302                             }
1303                             else
1304                                 setState(State.CHUNK);
1305                         }
1306                         break;
1307                     }
1308 
1309                     case CHUNK:
1310                     {
1311                         int remaining=_chunkLength - _chunkPosition;
1312                         if (remaining == 0)
1313                         {
1314                             setState(State.CHUNKED_CONTENT);
1315                         }
1316                         else
1317                         {
1318                             _contentChunk=buffer.asReadOnlyBuffer();
1319 
1320                             if (_contentChunk.remaining() > remaining)
1321                                 _contentChunk.limit(_contentChunk.position()+remaining);
1322                             remaining=_contentChunk.remaining();
1323 
1324                             _contentPosition += remaining;
1325                             _chunkPosition += remaining;
1326                             buffer.position(buffer.position()+remaining);
1327                             if (_handler.content(_contentChunk))
1328                                 return true;
1329                         }
1330                         break;
1331                     }
1332                     case CLOSED:
1333                     {
1334                         BufferUtil.clear(buffer);
1335                         return false;
1336                     }
1337                     
1338                     default: 
1339                         break;
1340                 }
1341             }
1342 
1343             return false;
1344         }
1345         catch(BadMessage e)
1346         {
1347             BufferUtil.clear(buffer);
1348 
1349             LOG.warn("BadMessage: "+e._code+(e._message!=null?" "+e._message:"")+" for "+_handler);
1350             if (DEBUG)
1351                 LOG.debug(e);
1352             setState(State.CLOSED);
1353             _handler.badMessage(e._code, e._message);
1354             return false;
1355         }
1356         catch(Exception e)
1357         {
1358             BufferUtil.clear(buffer);
1359 
1360             LOG.warn("Parsing Exception: "+e.toString()+" for "+_handler);
1361             if (DEBUG) 
1362                 LOG.debug(e);
1363             
1364             if (_state.ordinal()<=State.END.ordinal())
1365             {
1366                 setState(State.CLOSED);
1367                 _handler.badMessage(400,null);
1368             }
1369             else
1370             {
1371                 _handler.earlyEOF();
1372                 setState(State.CLOSED);
1373             }
1374 
1375             return false;
1376         }
1377     }
1378 
1379     /**
1380      * Notifies this parser that I/O code read a -1 and therefore no more data will arrive to be parsed.
1381      * Calling this method may result in an invocation to {@link HttpHandler#messageComplete()}, for
1382      * example when the content is delimited by the close of the connection.
1383      * If the parser is already in a state that does not need data (for example, it is idle waiting for
1384      * a request/response to be parsed), then calling this method is a no-operation.
1385      *
1386      * @return the result of the invocation to {@link HttpHandler#messageComplete()} if there has been
1387      * one, or false otherwise.
1388      */
1389     public boolean shutdownInput()
1390     {
1391         if (DEBUG)
1392             LOG.debug("shutdownInput {}", this);
1393 
1394         // was this unexpected?
1395         switch(_state)
1396         {
1397             case START:
1398             case END:
1399                 break;
1400 
1401             case EOF_CONTENT:
1402                 setState(State.END);
1403                 return _handler.messageComplete();
1404 
1405             case CLOSED:
1406                 break;
1407 
1408             default:
1409                 setState(State.END);
1410                 if (!_headResponse)
1411                     _handler.earlyEOF();
1412                 return _handler.messageComplete();
1413         }
1414 
1415         return false;
1416     }
1417 
1418     /* ------------------------------------------------------------------------------- */
1419     public void close()
1420     {
1421         if (DEBUG)
1422             LOG.debug("close {}", this);
1423         switch(_state)
1424         {
1425             case START:
1426             case CLOSED:
1427             case END:
1428                 break;
1429                 
1430             case EOF_CONTENT:
1431                 _handler.messageComplete();
1432                 break;
1433                 
1434             default:
1435                 if (_state.ordinal()>State.END.ordinal())
1436                 {
1437                     _handler.earlyEOF();
1438                     _handler.messageComplete();
1439                 }
1440                 else
1441                     LOG.warn("Closing {}",this);
1442         }
1443         setState(State.CLOSED);
1444         _endOfContent=EndOfContent.UNKNOWN_CONTENT;
1445         _contentLength=-1;
1446         _contentPosition=0;
1447         _responseStatus=0;
1448         _headerBytes=0;
1449         _contentChunk=null;
1450     }
1451 
1452     /* ------------------------------------------------------------------------------- */
1453     public void reset()
1454     {
1455         if (DEBUG)
1456             LOG.debug("reset {}", this);
1457         // reset state
1458         setState(State.START);
1459         _endOfContent=EndOfContent.UNKNOWN_CONTENT;
1460         _contentLength=-1;
1461         _contentPosition=0;
1462         _responseStatus=0;
1463         _contentChunk=null;
1464         _headerBytes=0;
1465         _host=false;
1466     }
1467 
1468     /* ------------------------------------------------------------------------------- */
1469     private void setState(State state)
1470     {
1471         if (DEBUG)
1472             LOG.debug("{} --> {}",_state,state);
1473         _state=state;
1474     }
1475 
1476     /* ------------------------------------------------------------------------------- */
1477     @Override
1478     public String toString()
1479     {
1480         return String.format("%s{s=%s,%d of %d}",
1481                 getClass().getSimpleName(),
1482                 _state,
1483                 _contentPosition,
1484                 _contentLength);
1485     }
1486 
1487     /* ------------------------------------------------------------ */
1488     /* ------------------------------------------------------------ */
1489     /* ------------------------------------------------------------ */
1490     /* Event Handler interface
1491      * These methods return true if the caller should process the events
1492      * so far received (eg return from parseNext and call HttpChannel.handle).
1493      * If multiple callbacks are called in sequence (eg 
1494      * headerComplete then messageComplete) from the same point in the parsing
1495      * then it is sufficient for the caller to process the events only once.
1496      */
1497     public interface HttpHandler<T>
1498     {
1499         public boolean content(T item);
1500 
1501         public boolean headerComplete();
1502 
1503         public boolean messageComplete();
1504 
1505         /**
1506          * This is the method called by parser when a HTTP Header name and value is found
1507          * @param field The field parsed
1508          * @return True if the parser should return to its caller
1509          */
1510         public boolean parsedHeader(HttpField field);
1511 
1512         /* ------------------------------------------------------------ */
1513         /** Called to signal that an EOF was received unexpectedly
1514          * during the parsing of a HTTP message
1515          * @return True if the parser should return to its caller
1516          */
1517         public void earlyEOF();
1518 
1519         /* ------------------------------------------------------------ */
1520         /** Called to signal that a bad HTTP message has been received.
1521          * @param status The bad status to send
1522          * @param reason The textual reason for badness
1523          */
1524         public void badMessage(int status, String reason);
1525         
1526         /* ------------------------------------------------------------ */
1527         /** @return the size in bytes of the per parser header cache
1528          */
1529         public int getHeaderCacheSize();
1530     }
1531 
1532     public interface RequestHandler<T> extends HttpHandler<T>
1533     {
1534         /**
1535          * This is the method called by parser when the HTTP request line is parsed
1536          * @param method The method as enum if of a known type
1537          * @param methodString The method as a string
1538          * @param uri The raw bytes of the URI.  These are copied into a ByteBuffer that will not be changed until this parser is reset and reused.
1539          * @param version
1540          * @return true if handling parsing should return.
1541          */
1542         public abstract boolean startRequest(HttpMethod method, String methodString, ByteBuffer uri, HttpVersion version);
1543 
1544         /**
1545          * This is the method called by the parser after it has parsed the host header (and checked it's format). This is
1546          * called after the {@link HttpHandler#parsedHeader(HttpField) methods and before
1547          * HttpHandler#headerComplete();
1548          */
1549         public abstract boolean parsedHostHeader(String host,int port);
1550     }
1551 
1552     public interface ResponseHandler<T> extends HttpHandler<T>
1553     {
1554         /**
1555          * This is the method called by parser when the HTTP request line is parsed
1556          */
1557         public abstract boolean startResponse(HttpVersion version, int status, String reason);
1558     }
1559 
1560     public Trie<HttpField> getFieldCache()
1561     {
1562         return _connectionFields;
1563     }
1564 
1565 }