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