1 /*
2  * Collie - An asynchronous event-driven network framework using Dlang development
3  *
4  * Copyright (C) 2015-2016  Shanghai Putao Technology Co., Ltd 
5  *
6  * Developer: putao's Dlang team
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 module collie.codec.http.parser;
12 
13 public import collie.codec.http.parser.parsertype;
14 
15 /** ubyte[] 为传过去字段里的位置引用,没有数据拷贝,自己使用的时候注意拷贝数据, 
16  bool 此段数据是否完结,可能只是数据的一部分。
17  */
18 alias CallBackData = void delegate(ref HTTPParser, ubyte[], bool);
19 alias CallBackNotify = void delegate(ref HTTPParser);
20 
21 struct HTTPParser
22 {
23     this(HTTPParserType ty, uint maxHeaderSize = 4096)
24     {
25 		rest(ty, maxHeaderSize);
26     }
27 
28     pragma(inline,true)
29     @property type()
30     {
31         return _type;
32     }
33 
34     pragma(inline,true)
35     @property isUpgrade()
36     {
37         return _upgrade;
38     }
39 
40     pragma(inline,true)
41     @property contentLength()
42     {
43         return _contentLength;
44     }
45 
46     pragma(inline,true)
47     @property isChunked()
48     {
49         return (_flags & HTTPParserFlags.F_CHUNKED) == 0 ? false : true;
50     }
51     //@property status() {return _statusCode;}
52     pragma(inline,true)
53     @property error()
54     {
55         return _httpErrno;
56     }
57 
58     pragma(inline,true)
59     @property errorString()
60     {
61         return error_string[_httpErrno];
62     }
63 
64     pragma(inline,true)
65     @property methodCode()
66     {
67         return _method;
68     }
69 
70     pragma(inline,true)
71     @property methodString()
72     {
73         return method_strings[_method];
74     }
75 
76     pragma(inline,true)
77     @property major()
78     {
79         return _httpMajor;
80     }
81 
82     //版本号首位
83     pragma(inline,true)
84     @property minor()
85     {
86         return _httpMinor;
87     }
88 
89     //版本号末尾
90     pragma(inline,true)
91     @property handleIng()
92     {
93         return _isHandle;
94     }
95 
96     pragma(inline)
97     @property handleIng(bool handle)
98     {
99         _isHandle = handle;
100     }
101 
102     pragma(inline,true)
103     @property skipBody()
104     {
105         return _skipBody;
106     }
107 
108     pragma(inline)
109     @property skipBody(bool skip)
110     {
111         return _skipBody = skip;
112     }
113     
114     pragma(inline,true)
115     @property keepalive()
116     {
117 		return _keepAlive;
118     }
119 
120     /** 回调函数指定 */
121     pragma(inline)
122     @property onMessageBegin(CallBackNotify cback)
123     {
124         _onMessageBegin = cback;
125     }
126 
127     pragma(inline)
128     @property onMessageComplete(CallBackNotify cback)
129     {
130         _onMessageComplete = cback;
131     }
132 
133     pragma(inline)
134     @property onHeaderComplete(CallBackNotify cback)
135     {
136         _onHeadersComplete = cback;
137     }
138 
139     pragma(inline)
140     @property onChunkHeader(CallBackNotify cback)
141     {
142         _onChunkHeader = cback;
143     }
144 
145     pragma(inline)
146     @property onChunkComplete(CallBackNotify cback)
147     {
148         _onChunkComplete = cback;
149     }
150 
151     pragma(inline)
152     @property onUrl(CallBackData cback)
153     {
154         _onUrl = cback;
155     }
156 
157     pragma(inline)
158     @property onStatus(CallBackData cback)
159     {
160         _onStatus = cback;
161     }
162 
163     pragma(inline)
164     @property onHeaderField(CallBackData cback)
165     {
166         _onHeaderField = cback;
167     }
168 
169     pragma(inline)
170     @property onHeaderValue(CallBackData cback)
171     {
172         _onHeaderValue = cback;
173     }
174 
175     pragma(inline)
176     @property onBody(CallBackData cback)
177     {
178         _onBody = cback;
179     }
180 
181     pragma(inline)
182 		void rest(HTTPParserType ty, uint maxHeaderSize = 4096)
183     {
184         type = ty;
185 		_maxHeaderSize = maxHeaderSize;
186         _state = (
187             type == HTTPParserType.HTTP_REQUEST ? HTTPParserState.s_start_req : (
188             type == HTTPParserType.HTTP_RESPONSE ? HTTPParserState.s_start_res
189             : HTTPParserState.s_start_req_or_res));
190         _httpErrno = HTTPParserErrno.HPE_OK;
191         _flags = HTTPParserFlags.F_ZERO;
192 		_isHandle = false;
193 		_skipBody = false;
194 		_keepAlive = 0x00;
195     }
196 
197 protected:
198     CallBackNotify _onMessageBegin;
199 
200     CallBackNotify _onHeadersComplete;
201 
202     CallBackNotify _onMessageComplete;
203 
204     CallBackNotify _onChunkHeader;
205 
206     CallBackNotify _onChunkComplete;
207 
208     CallBackData _onUrl;
209 
210     CallBackData _onStatus;
211 
212     CallBackData _onHeaderField;
213 
214     CallBackData _onHeaderValue;
215 
216     CallBackData _onBody;
217 
218 public:
219 
220     pragma(inline)
221     bool bodyIsFinal()
222     {
223         return _state == HTTPParserState.s_message_done;
224     }
225 
226     ulong httpParserExecute(ubyte[] data)
227     {
228         handleIng = true;
229         scope (exit)
230             handleIng = false;
231         ubyte c, ch;
232         byte unhexVal;
233         size_t mHeaderFieldMark = size_t.max;
234         size_t mHeaderValueMark = size_t.max;
235         size_t mUrlMark = size_t.max;
236         size_t mBodyMark = size_t.max;
237         size_t mStatusMark = size_t.max;
238         size_t maxP = cast(long) data.length;
239         size_t p = 0;
240         if (_httpErrno != HTTPParserErrno.HPE_OK)
241         {
242             return 0;
243         }
244         if (data.length == 0)
245         {
246             switch (_state)
247             {
248             case HTTPParserState.s_body_identity_eof:
249                 /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
250 					 * we got paused.
251 					 */
252                 mixin(
253                     CALLBACK_NOTIFY_NOADVANCE("MessageComplete"));
254                 return 0;
255 
256             case HTTPParserState.s_dead:
257             case HTTPParserState.s_start_req_or_res:
258             case HTTPParserState.s_start_res:
259             case HTTPParserState.s_start_req:
260                 return 0;
261 
262             default:
263                 //_httpErrno = HTTPParserErrno.HPE_INVALID_EOF_STATE);
264                 _httpErrno = HTTPParserErrno.HPE_INVALID_EOF_STATE;
265                 return 1;
266             }
267         }
268 
269         if (_state == HTTPParserState.s_header_field)
270             mHeaderFieldMark = 0;
271         if (_state == HTTPParserState.s_header_value)
272             mHeaderValueMark = 0;
273         switch (_state)
274         {
275         case HTTPParserState.s_req_path:
276         case HTTPParserState.s_req_schema:
277         case HTTPParserState.s_req_schema_slash:
278         case HTTPParserState.s_req_schema_slash_slash:
279         case HTTPParserState.s_req_server_start:
280         case HTTPParserState.s_req_server:
281         case HTTPParserState.s_req_server_with_at:
282         case HTTPParserState.s_req_query_string_start:
283         case HTTPParserState.s_req_query_string:
284         case HTTPParserState.s_req_fragment_start:
285         case HTTPParserState.s_req_fragment:
286             mUrlMark = 0;
287             break;
288         case HTTPParserState.s_res_status:
289             mStatusMark = 0;
290             break;
291         default:
292             break;
293         }
294         for (; p < maxP; ++p)
295         {
296             ch = data[p];
297             if (_state <= HTTPParserState.s_headers_done)
298             {
299                 _nread += 1;
300                 if (_nread > _maxHeaderSize)
301                 {
302                     _httpErrno = HTTPParserErrno.HPE_HEADER_OVERFLOW;
303                     goto error;
304                 }
305             }
306 
307         reexecute:
308             switch (_state)
309             {
310             case HTTPParserState.s_dead:
311                 /* this _state is used after a 'Connection: close' message
312 					 * the parser will error out if it reads another message
313 					 */
314                 if (ch == CR || ch == LF)
315                     break;
316 
317                 _httpErrno = HTTPParserErrno.HPE_CLOSED_CONNECTION;
318                 goto error;
319             case HTTPParserState.s_start_req_or_res:
320                 {
321                     if (ch == CR || ch == LF)
322                         break;
323                     _flags = HTTPParserFlags.F_ZERO;
324                     _contentLength = ulong.max;
325 
326                     if (ch == 'H')
327                     {
328                         _state = HTTPParserState.s_res_or_resp_H;
329 
330                         mixin(CALLBACK_NOTIFY("MessageBegin")); // 开始处理
331 
332                     }
333                     else
334                     {
335                         type = HTTPParserType.HTTP_REQUEST;
336                         _state = HTTPParserState.s_start_req;
337                         goto reexecute;
338                     }
339 
340                     break;
341                 }
342             case HTTPParserState.s_res_or_resp_H:
343                 if (ch == 'T')
344                 {
345                     type = HTTPParserType.HTTP_RESPONSE;
346                     _state = HTTPParserState.s_res_HT;
347                 }
348                 else
349                 {
350                     if (ch != 'E')
351                     {
352                         _httpErrno = HTTPParserErrno.HPE_INVALID_CONSTANT;
353                         goto error;
354                     }
355 
356                     type = HTTPParserType.HTTP_REQUEST;
357                     _method = HTTPMethod.HTTP_HEAD;
358                     _index = 2;
359                     _state = HTTPParserState.s_req_method;
360                 }
361                 break;
362 
363             case HTTPParserState.s_start_res:
364                 {
365                     _flags = HTTPParserFlags.F_ZERO;
366                     _contentLength = ulong.max;
367 
368                     switch (ch)
369                     {
370                     case 'H':
371                         _state = HTTPParserState.s_res_H;
372                         break;
373 
374                     case CR:
375                     case LF:
376                         break;
377 
378                     default:
379                         _httpErrno = HTTPParserErrno.HPE_INVALID_CONSTANT;
380                         goto error;
381                     }
382                     mixin(CALLBACK_NOTIFY("MessageBegin"));
383                     break;
384                 }
385             case HTTPParserState.s_res_H:
386                 mixin(STRICT_CHECK("ch != 'T'"));
387                 _state = HTTPParserState.s_res_HT;
388                 break;
389 
390             case HTTPParserState.s_res_HT:
391                 //STRICT_CHECK(ch != 'T');
392                 mixin(STRICT_CHECK("ch != 'T'"));
393                 _state = HTTPParserState.s_res_HTT;
394                 break;
395 
396             case HTTPParserState.s_res_HTT:
397                 //STRICT_CHECK(ch != 'P');
398                 mixin(STRICT_CHECK("ch != 'P'"));
399                 _state = HTTPParserState.s_res_HTTP;
400                 break;
401 
402             case HTTPParserState.s_res_HTTP:
403                 //STRICT_CHECK(ch != '/');
404                 mixin(STRICT_CHECK("ch != '/'"));
405                 _state = HTTPParserState.s_res_first_http_major;
406                 break;
407 
408             case HTTPParserState.s_res_first_http_major:
409                 if (ch < '0' || ch > '9')
410                 {
411                     _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
412                     goto error;
413                 }
414 
415                 _httpMajor = cast(ushort)(ch - '0');
416                 _state = HTTPParserState.s_res_http_major;
417                 break;
418 
419                 /* major HTTP version or dot */
420             case HTTPParserState.s_res_http_major:
421                 {
422                     if (ch == '.')
423                     {
424                         _state = HTTPParserState.s_res_first_http_minor;
425                         break;
426                     }
427 
428                     if (!mixin(IS_NUM("ch")))
429                     {
430                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
431                         goto error;
432                     }
433 
434                     _httpMajor *= 10;
435                     _httpMajor += ch - '0';
436 
437                     if (_httpMajor > 999)
438                     {
439                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
440                         goto error;
441                     }
442 
443                     break;
444                 }
445 
446                 /* first digit of minor HTTP version */
447             case HTTPParserState.s_res_first_http_minor:
448                 if (!mixin(IS_NUM("ch")))
449                 {
450                     _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
451                     goto error;
452                 }
453 
454                 _httpMinor = cast(ushort)(ch - '0');
455                 _state = HTTPParserState.s_res_http_minor;
456                 break;
457 
458                 /* minor HTTP version or end of request line */
459             case HTTPParserState.s_res_http_minor:
460                 {
461                     if (ch == ' ')
462                     {
463                         _state = HTTPParserState.s_res_first_status_code;
464                         break;
465                     }
466 
467                     if (!mixin(IS_NUM("ch")))
468                     {
469                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
470                         goto error;
471                     }
472 
473                     _httpMinor *= 10;
474                     _httpMinor += ch - '0';
475 
476                     if (_httpMinor > 999)
477                     {
478                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
479                         goto error;
480                     }
481 
482                     break;
483                 }
484 
485             case HTTPParserState.s_res_first_status_code:
486                 {
487                     if (!mixin(IS_NUM("ch")))
488                     {
489                         if (ch == ' ')
490                         {
491                             break;
492                         }
493 
494                         _httpErrno = HTTPParserErrno.HPE_INVALID_STATUS;
495                         goto error;
496                     }
497                     _statusCode = ch - '0';
498                     _state = HTTPParserState.s_res_status_code;
499                     break;
500                 }
501 
502             case HTTPParserState.s_res_status_code:
503                 {
504                     if (!mixin(IS_NUM("ch")))
505                     {
506                         switch (ch)
507                         {
508                         case ' ':
509                             _state = HTTPParserState.s_res_status_start;
510                             break;
511                         case CR:
512                             _state = HTTPParserState.s_res_line_almost_done;
513                             break;
514                         case LF:
515                             _state = HTTPParserState.s_header_field_start;
516                             break;
517                         default:
518                             _httpErrno = HTTPParserErrno.HPE_INVALID_STATUS;
519                             goto error;
520                         }
521                         break;
522                     }
523 
524                     _statusCode *= 10;
525                     _statusCode += ch - '0';
526 
527                     if (_statusCode > 999)
528                     {
529                         _httpErrno = HTTPParserErrno.HPE_INVALID_STATUS;
530                         goto error;
531                     }
532 
533                     break;
534                 }
535 
536             case HTTPParserState.s_res_status_start:
537                 {
538                     if (ch == CR)
539                     {
540                         _state = HTTPParserState.s_res_line_almost_done;
541                         break;
542                     }
543 
544                     if (ch == LF)
545                     {
546                         _state = HTTPParserState.s_header_field_start;
547                         break;
548                     }
549 
550                     //MARK(status);
551                     if (mStatusMark == size_t.max)
552                     {
553                         mStatusMark = p;
554                     }
555                     _state = HTTPParserState.s_res_status;
556                     _index = 0;
557                     break;
558                 }
559 
560             case HTTPParserState.s_res_status:
561                 if (ch == CR)
562                 {
563                     _state = HTTPParserState.s_res_line_almost_done;
564                     mixin(CALLBACK_DATA("Status"));
565                     break;
566                 }
567 
568                 if (ch == LF)
569                 {
570                     _state = HTTPParserState.s_header_field_start;
571                     //statusCall();
572                     mixin(CALLBACK_DATA("Status"));
573                     break;
574                 }
575 
576                 break;
577 
578             case HTTPParserState.s_res_line_almost_done:
579                 mixin(STRICT_CHECK("ch != LF"));
580                 _state = HTTPParserState.s_header_field_start;
581                 break;
582 
583             case HTTPParserState.s_start_req:
584                 {
585                     if (ch == CR || ch == LF)
586                         break;
587                     _flags = HTTPParserFlags.F_ZERO;
588                     _contentLength = ulong.max;
589 
590                     if (!mixin(IS_ALPHA("ch")))
591                     {
592                         //error("err0");
593                         _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
594                         goto error;
595                     }
596 
597                     _index = 1;
598                     switch (ch)
599                     {
600                     case 'A':
601                         _method = HTTPMethod.HTTP_ACL;
602                         break;
603                     case 'B':
604                         _method = HTTPMethod.HTTP_BIND;
605                         break;
606                     case 'C':
607                         _method = HTTPMethod.HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
608                     case 'D':
609                         _method = HTTPMethod.HTTP_DELETE;
610                         break;
611                     case 'G':
612                         _method = HTTPMethod.HTTP_GET;
613                         break;
614                     case 'H':
615                         _method = HTTPMethod.HTTP_HEAD;
616                         break;
617                     case 'L':
618                         _method = HTTPMethod.HTTP_LOCK; /* or LINK */ break;
619                     case 'M':
620                         _method = HTTPMethod.HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
621                     case 'N':
622                         _method = HTTPMethod.HTTP_NOTIFY;
623                         break;
624                     case 'O':
625                         _method = HTTPMethod.HTTP_OPTIONS;
626                         break;
627                     case 'P':
628                         _method = HTTPMethod.HTTP_POST;
629                         /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
630                         break;
631                     case 'R':
632                         _method = HTTPMethod.HTTP_REPORT; /* or REBIND */ break;
633                     case 'S':
634                         _method = HTTPMethod.HTTP_SUBSCRIBE; /* or SEARCH */ break;
635                     case 'T':
636                         _method = HTTPMethod.HTTP_TRACE;
637                         break;
638                     case 'U':
639                         _method = HTTPMethod.HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
640                     default:
641                         //error("err0");
642                         _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
643                         goto error;
644                     }
645                     _state = HTTPParserState.s_req_method;
646 
647                     mixin(CALLBACK_NOTIFY("MessageBegin"));
648                     break;
649                 }
650 
651             case HTTPParserState.s_req_method:
652                 {
653                     if (ch == '\0')
654                     {
655                         //error("err0");
656                         _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
657                         goto error;
658                     }
659 
660                     string matcher = method_strings[_method];
661                     if (ch == ' ' && matcher.length == _index)
662                     {
663                         _state = HTTPParserState.s_req_spaces_before_url;
664                     }
665                     else if (ch == matcher[_index])
666                     {
667                         //; /* nada */
668                     }
669                     else if (_method == HTTPMethod.HTTP_CONNECT)
670                     {
671                         if (_index == 1 && ch == 'H')
672                         {
673                             _method = HTTPMethod.HTTP_CHECKOUT;
674                         }
675                         else if (_index == 2 && ch == 'P')
676                         {
677                             _method = HTTPMethod.HTTP_COPY;
678                         }
679                         else
680                         {
681                             //error("err0");
682                             _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
683                             goto error;
684                         }
685                     }
686                     else if (_method == HTTPMethod.HTTP_MKCOL)
687                     {
688                         if (_index == 1 && ch == 'O')
689                         {
690                             _method = HTTPMethod.HTTP_MOVE;
691                         }
692                         else if (_index == 1 && ch == 'E')
693                         {
694                             _method = HTTPMethod.HTTP_MERGE;
695                         }
696                         else if (_index == 1 && ch == '-')
697                         {
698                             _method = HTTPMethod.HTTP_MSEARCH;
699                         }
700                         else if (_index == 2 && ch == 'A')
701                         {
702                             _method = HTTPMethod.HTTP_MKACTIVITY;
703                         }
704                         else if (_index == 3 && ch == 'A')
705                         {
706                             _method = HTTPMethod.HTTP_MKCALENDAR;
707                         }
708                         else
709                         {
710                             //error("err0");
711                             _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
712                             goto error;
713                         }
714                     }
715                     else if (_method == HTTPMethod.HTTP_SUBSCRIBE)
716                     {
717                         if (_index == 1 && ch == 'E')
718                         {
719                             _method = HTTPMethod.HTTP_SEARCH;
720                         }
721                         else
722                         {
723                             //error("err0");
724                             _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
725                             goto error;
726                         }
727                     }
728                     else if (_method == HTTPMethod.HTTP_REPORT)
729                     {
730                         if (_index == 2 && ch == 'B')
731                         {
732                             //error("err0");
733                             _method = HTTPMethod.HTTP_REBIND;
734                         }
735                         else
736                         {
737                             _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
738                             goto error;
739                         }
740                     }
741                     else if (_index == 1)
742                     {
743                         if (_method == HTTPMethod.HTTP_POST)
744                         {
745 
746                             if (ch == 'R')
747                             {
748                                 _method = HTTPMethod.HTTP_PROPFIND; /* or HTTP_PROPPATCH */
749                             }
750                             else if (ch == 'U')
751                             {
752                                 _method = HTTPMethod.HTTP_PUT; /* or HTTP_PURGE */
753                             }
754                             else if (ch == 'A')
755                             {
756                                 _method = HTTPMethod.HTTP_PATCH;
757                             }
758                             else
759                             {
760                                 //error("err0");
761                                 _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
762                                 goto error;
763                             }
764                         }
765                         else if (_method == HTTPMethod.HTTP_LOCK)
766                         {
767                             if (ch == 'I')
768                             {
769                                 _method = HTTPMethod.HTTP_LINK;
770                             }
771                             else
772                             {
773                                 //error("err0");
774                                 _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
775                                 goto error;
776                             }
777                         }
778                     }
779                     else if (_index == 2)
780                     {
781                         if (_method == HTTPMethod.HTTP_PUT)
782                         {
783                             if (ch == 'R')
784                             {
785                                 _method = HTTPMethod.HTTP_PURGE;
786                             }
787                             else
788                             {
789                                 //error("err0");
790                                 _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
791                                 goto error;
792                             }
793                         }
794                         else if (_method == HTTPMethod.HTTP_UNLOCK)
795                         {
796                             if (ch == 'S')
797                             {
798                                 _method = HTTPMethod.HTTP_UNSUBSCRIBE;
799                             }
800                             else if (ch == 'B')
801                             {
802                                 _method = HTTPMethod.HTTP_UNBIND;
803                             }
804                             else
805                             {
806                                 //error("err0");
807                                 _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
808                                 goto error;
809                             }
810                         }
811                         else
812                         {
813                             //error("err0");
814                             _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
815                             goto error;
816                         }
817                     }
818                     else if (_index == 4 && _method == HTTPMethod.HTTP_PROPFIND && ch == 'P')
819                     {
820                         _method = HTTPMethod.HTTP_PROPPATCH;
821                     }
822                     else if (_index == 3 && _method == HTTPMethod.HTTP_UNLOCK && ch == 'I')
823                     {
824                         _method = HTTPMethod.HTTP_UNLINK;
825                     }
826                     else
827                     {
828                         //error("err0");
829                         _httpErrno = HTTPParserErrno.HPE_INVALID_METHOD;
830                         goto error;
831                     }
832 
833                     ++_index;
834                     break;
835                 }
836 
837             case HTTPParserState.s_req_spaces_before_url:
838                 {
839                     if (ch == ' ')
840                         break;
841 
842                     //MARK(url);
843                     if (mUrlMark == size_t.max)
844                     {
845                         mUrlMark = p;
846                     }
847                     if (_method == HTTPMethod.HTTP_CONNECT)
848                     {
849                         _state = HTTPParserState.s_req_server_start;
850                     }
851 
852                     _state = parseURLchar(_state, ch);
853                     if (_state == HTTPParserState.s_dead)
854                     {
855                         _httpErrno = HTTPParserErrno.HPE_INVALID_URL;
856                         goto error;
857                     }
858 
859                     break;
860                 }
861 
862             case HTTPParserState.s_req_schema:
863             case HTTPParserState.s_req_schema_slash:
864             case HTTPParserState.s_req_schema_slash_slash:
865             case HTTPParserState.s_req_server_start:
866                 {
867                     switch (ch)
868                     {
869                         /* No whitespace allowed here */
870                     case ' ':
871                     case CR:
872                     case LF:
873                         _httpErrno = HTTPParserErrno.HPE_INVALID_URL;
874                         goto error;
875                     default:
876                         _state = parseURLchar(_state, ch);
877                         if (_state == HTTPParserState.s_dead)
878                         {
879                             _httpErrno = HTTPParserErrno.HPE_INVALID_URL;
880                             goto error;
881                         }
882                     }
883 
884                     break;
885                 }
886 
887             case HTTPParserState.s_req_server:
888             case HTTPParserState.s_req_server_with_at:
889             case HTTPParserState.s_req_path:
890             case HTTPParserState.s_req_query_string_start:
891             case HTTPParserState.s_req_query_string:
892             case HTTPParserState.s_req_fragment_start:
893             case HTTPParserState.s_req_fragment:
894                 {
895                     switch (ch)
896                     {
897                     case ' ':
898                         _state = HTTPParserState.s_req_http_start;
899                         mixin(CALLBACK_DATA("Url"));
900                         break;
901                     case CR:
902                     case LF:
903                         _httpMajor = 0;
904                         _httpMinor = 9;
905                         _state = (ch == CR) ? HTTPParserState.s_req_line_almost_done
906                             : HTTPParserState.s_header_field_start;
907                         mixin(CALLBACK_DATA("Url"));
908                         break;
909                     default:
910                         _state = parseURLchar(_state, ch);
911                         if (_state == HTTPParserState.s_dead)
912                         {
913                             _httpErrno = HTTPParserErrno.HPE_INVALID_URL;
914                             goto error;
915                         }
916                     }
917                     break;
918                 }
919 
920             case HTTPParserState.s_req_http_start:
921                 switch (ch)
922                 {
923                 case 'H':
924                     _state = HTTPParserState.s_req_http_H;
925                     break;
926                 case ' ':
927                     break;
928                 default:
929                     _httpErrno = HTTPParserErrno.HPE_INVALID_CONSTANT;
930                     goto error;
931                 }
932                 break;
933 
934             case HTTPParserState.s_req_http_H:
935                 mixin(STRICT_CHECK("ch != 'T'"));
936                 _state = HTTPParserState.s_req_http_HT;
937                 break;
938 
939             case HTTPParserState.s_req_http_HT:
940                 //STRICT_CHECK(ch != 'T');
941                 mixin(STRICT_CHECK("ch != 'T'"));
942                 _state = HTTPParserState.s_req_http_HTT;
943                 break;
944 
945             case HTTPParserState.s_req_http_HTT:
946                 //STRICT_CHECK(ch != 'P');
947                 mixin(STRICT_CHECK("ch != 'P'"));
948                 _state = HTTPParserState.s_req_http_HTTP;
949                 break;
950 
951             case HTTPParserState.s_req_http_HTTP:
952                 //STRICT_CHECK(ch != '/');
953                 mixin(STRICT_CHECK("ch != '/'"));
954                 _state = HTTPParserState.s_req_first_http_major;
955                 break;
956 
957                 /* first digit of major HTTP version */
958             case HTTPParserState.s_req_first_http_major:
959                 if (ch < '1' || ch > '9')
960                 {
961                     _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
962                     goto error;
963                 }
964 
965                 _httpMajor = cast(ushort)(ch - '0');
966                 _state = HTTPParserState.s_req_http_major;
967                 break;
968 
969                 /* major HTTP version or dot */
970             case HTTPParserState.s_req_http_major:
971                 {
972                     if (ch == '.')
973                     {
974                         _state = HTTPParserState.s_req_first_http_minor;
975                         break;
976                     }
977 
978                     if (!mixin(IS_NUM("ch")))
979                     {
980                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
981                         goto error;
982                     }
983 
984                     _httpMajor *= 10;
985                     _httpMajor += ch - '0';
986 
987                     if (_httpMajor > 999)
988                     {
989                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
990                         goto error;
991                     }
992 
993                     break;
994                 }
995 
996                 /* first digit of minor HTTP version */
997             case HTTPParserState.s_req_first_http_minor:
998                 if (!mixin(IS_NUM("ch")))
999                 {
1000                     _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
1001                     goto error;
1002                 }
1003 
1004                 _httpMinor = cast(ushort)(ch - '0');
1005                 _state = HTTPParserState.s_req_http_minor;
1006                 break;
1007 
1008                 /* minor HTTP version or end of request line */
1009             case HTTPParserState.s_req_http_minor:
1010                 {
1011                     if (ch == CR)
1012                     {
1013                         _state = HTTPParserState.s_req_line_almost_done;
1014                         break;
1015                     }
1016 
1017                     if (ch == LF)
1018                     {
1019                         _state = HTTPParserState.s_header_field_start;
1020                         break;
1021                     }
1022 
1023                     /* XXX allow spaces after digit? */
1024 
1025                     if (!mixin(IS_NUM("ch")))
1026                     {
1027                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
1028                         goto error;
1029                     }
1030 
1031                     _httpMinor *= 10;
1032                     _httpMinor += ch - '0';
1033 
1034                     if (_httpMinor > 999)
1035                     {
1036                         _httpErrno = HTTPParserErrno.HPE_INVALID_VERSION;
1037                         goto error;
1038                     }
1039 
1040                     break;
1041                 }
1042 
1043                 /* end of request line */
1044             case HTTPParserState.s_req_line_almost_done:
1045                 {
1046                     if (ch != LF)
1047                     {
1048                         _httpErrno = HTTPParserErrno.HPE_LF_EXPECTED;
1049                         goto error;
1050                     }
1051 
1052                     _state = HTTPParserState.s_header_field_start;
1053                     break;
1054                 }
1055 
1056             case HTTPParserState.s_header_field_start:
1057                 {
1058                     if (ch == CR)
1059                     {
1060                         _state = HTTPParserState.s_headers_almost_done;
1061                         break;
1062                     }
1063 
1064                     if (ch == LF)
1065                     {
1066                         /* they might be just sending \n instead of \r\n so this would be
1067 						 * the second \n to denote the end of headers*/
1068                         _state = HTTPParserState.s_headers_almost_done;
1069                         //goto reexecute;
1070                         goto reexecute;
1071                     }
1072 
1073                     c = tokens[ch];
1074 
1075                     if (!c)
1076                     {
1077                         _httpErrno = HTTPParserErrno.HPE_INVALID_HEADER_TOKEN;
1078                         goto error;
1079                     }
1080 
1081                     if (mHeaderFieldMark == size_t.max)
1082                     {
1083                         mHeaderFieldMark = p;
1084                     }
1085 
1086                     _index = 0;
1087                     _state = HTTPParserState.s_header_field;
1088 
1089                     switch (c)
1090                     {
1091                     case 'c':
1092                          _headerState = HTTPParserHeaderstates.h_C;
1093                         break;
1094 
1095                     case 'p':
1096                          _headerState = HTTPParserHeaderstates.h_matching_proxy_connection;
1097                         break;
1098 
1099                     case 't':
1100                          _headerState = HTTPParserHeaderstates.h_matching_transfer_encoding;
1101                         break;
1102 
1103                     case 'u':
1104                          _headerState = HTTPParserHeaderstates.h_matching_upgrade;
1105                         break;
1106 
1107                     default:
1108                          _headerState = HTTPParserHeaderstates.h_general;
1109                         break;
1110                     }
1111                     break;
1112                 }
1113 
1114             case HTTPParserState.s_header_field:
1115                 {
1116                     const long start = p;
1117                     for (; p < maxP; p++)
1118                     {
1119                         ch = data[p];
1120                         c = tokens[ch];
1121 
1122                         if (!c)
1123                             break;
1124 
1125                         switch ( _headerState)
1126                         {
1127                         case HTTPParserHeaderstates.h_general:
1128                             break;
1129 
1130                         case HTTPParserHeaderstates.h_C:
1131                             _index++;
1132                              _headerState = (
1133                                 c == 'o' ? HTTPParserHeaderstates.h_CO
1134                                 : HTTPParserHeaderstates.h_general);
1135                             break;
1136 
1137                         case HTTPParserHeaderstates.h_CO:
1138                             _index++;
1139                              _headerState = (
1140                                 c == 'n' ? HTTPParserHeaderstates.h_CON
1141                                 : HTTPParserHeaderstates.h_general);
1142                             break;
1143 
1144                         case HTTPParserHeaderstates.h_CON:
1145                             _index++;
1146                             switch (c)
1147                             {
1148                             case 'n':
1149                                  _headerState = HTTPParserHeaderstates.h_matching_connection;
1150                                 break;
1151                             case 't':
1152                                  _headerState = HTTPParserHeaderstates.h_matching_content_length;
1153                                 break;
1154                             default:
1155                                  _headerState = HTTPParserHeaderstates.h_general;
1156                                 break;
1157                             }
1158                             break;
1159 
1160                             /* connection */
1161 
1162                         case HTTPParserHeaderstates.h_matching_connection:
1163                             _index++;
1164                             if (_index > CONNECTION.length || c != CONNECTION[_index])
1165                             {
1166                                  _headerState = HTTPParserHeaderstates.h_general;
1167                             }
1168                             else if (_index == CONNECTION.length - 1)
1169                             {
1170                                  _headerState = HTTPParserHeaderstates.h_connection;
1171                             }
1172                             break;
1173 
1174                             /* proxy-connection */
1175 
1176                         case HTTPParserHeaderstates.h_matching_proxy_connection:
1177                             _index++;
1178                             if (_index > PROXY_CONNECTION.length || c != PROXY_CONNECTION[_index])
1179                             {
1180                                  _headerState = HTTPParserHeaderstates.h_general;
1181                             }
1182                             else if (_index == PROXY_CONNECTION.length)
1183                             {
1184                                  _headerState = HTTPParserHeaderstates.h_connection;
1185                             }
1186                             break;
1187 
1188                             /* content-length */
1189 
1190                         case HTTPParserHeaderstates.h_matching_content_length:
1191                             _index++;
1192 							if (_index > CONTENT_LENGTH.length || c != CONTENT_LENGTH[_index])
1193                             {
1194                                  _headerState = HTTPParserHeaderstates.h_general;
1195                             }
1196 							else if (_index == CONTENT_LENGTH.length - 1)
1197                             {
1198                                 if (_flags & HTTPParserFlags.F_CONTENTLENGTH)
1199                                 {
1200                                     _httpErrno = HTTPParserErrno.HPE_UNEXPECTED_CONTENT_LENGTH;
1201                                     goto error;
1202                                 }
1203                                  _headerState = HTTPParserHeaderstates.h_content_length;
1204                                 _flags |= HTTPParserFlags.F_CONTENTLENGTH;
1205                             }
1206                             break;
1207 
1208                             /* transfer-encoding */
1209 
1210                         case HTTPParserHeaderstates.h_matching_transfer_encoding:
1211                             _index++;
1212                             if (_index > TRANSFER_ENCODING.length || c != TRANSFER_ENCODING[_index])
1213                             {
1214                                  _headerState = HTTPParserHeaderstates.h_general;
1215                             }
1216                             else if (_index == TRANSFER_ENCODING.length - 1)
1217                             {
1218                                  _headerState = HTTPParserHeaderstates.h_transfer_encoding;
1219                             }
1220                             break;
1221 
1222                             /* upgrade */
1223 
1224                         case HTTPParserHeaderstates.h_matching_upgrade:
1225                             _index++;
1226                             if (_index > UPGRADE.length || c != UPGRADE[_index])
1227                             {
1228                                  _headerState = HTTPParserHeaderstates.h_general;
1229                             }
1230                             else if (_index == UPGRADE.length - 1)
1231                             {
1232                                  _headerState = HTTPParserHeaderstates.h_upgrade;
1233                             }
1234                             break;
1235 
1236                         case HTTPParserHeaderstates.h_connection:
1237                         case HTTPParserHeaderstates.h_content_length:
1238                         case HTTPParserHeaderstates.h_transfer_encoding:
1239                         case HTTPParserHeaderstates.h_upgrade:
1240                             if (
1241                                     ch != ' ')
1242                                  _headerState = HTTPParserHeaderstates.h_general;
1243                             break;
1244 
1245                         default:
1246                             assert(false, "Unknown  _headerState");
1247                             //	break;
1248                         }
1249                     }
1250 
1251                     //COUNT_HEADER_SIZE(p - start);
1252                     _nread += (p - start);
1253                     if (_nread > _maxHeaderSize)
1254                     {
1255                         _httpErrno = HTTPParserErrno.HPE_HEADER_OVERFLOW;
1256                         goto error;
1257                     }
1258 
1259                     if (p == maxP)
1260                     {
1261                         --p;
1262                         break;
1263                     }
1264 
1265                     if (ch == ':')
1266                     {
1267                         _state = HTTPParserState.s_header_value_discard_ws;
1268                         mixin(CALLBACK_DATA("HeaderField"));
1269                         break;
1270                     }
1271 
1272                     _httpErrno = HTTPParserErrno.HPE_INVALID_HEADER_TOKEN;
1273                     goto error;
1274                 }
1275 
1276             case HTTPParserState.s_header_value_discard_ws:
1277                 if (ch == ' ' || ch == '\t')
1278                     break;
1279 
1280                 if (ch == CR)
1281                 {
1282                     _state = HTTPParserState.s_header_value_discard_ws_almost_done;
1283                     break;
1284                 }
1285 
1286                 if (ch == LF)
1287                 {
1288                     _state = HTTPParserState.s_header_value_discard_lws;
1289                     break;
1290                 }
1291                 goto case;
1292                 /* FALLTHROUGH */
1293 
1294             case HTTPParserState.s_header_value_start:
1295                 {
1296                     //MARK(header_value);
1297                     if (mHeaderValueMark == size_t.max)
1298                     {
1299                         mHeaderValueMark = p;
1300                     }
1301                     _state = HTTPParserState.s_header_value;
1302                     _index = 0;
1303 
1304                     c = ch | 0x20; //LOWER(ch);
1305 
1306                     switch ( _headerState)
1307                     {
1308                     case HTTPParserHeaderstates.h_upgrade:
1309                         _flags |= HTTPParserFlags.F_UPGRADE;
1310                          _headerState = HTTPParserHeaderstates.h_general;
1311                         break;
1312 
1313                     case HTTPParserHeaderstates.h_transfer_encoding:
1314                         /* looking for 'Transfer-Encoding: chunked' */
1315                         if ('c' == c)
1316                         {
1317                              _headerState = HTTPParserHeaderstates
1318                                 .h_matching_transfer_encoding_chunked;
1319                         }
1320                         else
1321                         {
1322                              _headerState = HTTPParserHeaderstates.h_general;
1323                         }
1324                         break;
1325 
1326                     case HTTPParserHeaderstates.h_content_length:
1327                         if (!mixin(IS_NUM("ch")))
1328                         {
1329                             _httpErrno = HTTPParserErrno.HPE_INVALID_CONTENT_LENGTH;
1330                             goto error;
1331                         }
1332 
1333                         _contentLength = ch - '0';
1334                         break;
1335 
1336                     case HTTPParserHeaderstates.h_connection:
1337                         /* looking for 'Connection: keep-alive' */
1338                         if (c == 'k')
1339                         {
1340                              _headerState = HTTPParserHeaderstates.h_matching_connection_keep_alive;
1341                             _keepAlive = 0x01;
1342                             /* looking for 'Connection: close' */
1343                         }
1344                         else if (c == 'c')
1345                         {
1346                              _headerState = HTTPParserHeaderstates.h_matching_connection_close;
1347 							_keepAlive = 0x02;
1348                         }
1349                         else if (c == 'u')
1350                         {
1351                              _headerState = HTTPParserHeaderstates.h_matching_connection_upgrade;
1352 							_keepAlive = 0x03;
1353                         }
1354                         else
1355                         {
1356                              _headerState = HTTPParserHeaderstates.h_matching_connection_token;
1357 							_keepAlive = 0x04;
1358                         }
1359                         break;
1360 
1361                         /* Multi-value `Connection` header */
1362                     case HTTPParserHeaderstates.h_matching_connection_token_start:
1363                         break;
1364 
1365                     default:
1366                          _headerState = HTTPParserHeaderstates.h_general;
1367                         break;
1368                     }
1369                     break;
1370                 }
1371 
1372             case HTTPParserState.s_header_value: //BUG,找不到结束
1373             {
1374                     const long start = p;
1375                     auto h_state =  _headerState;
1376                     for (; p < maxP; p++)
1377                     {
1378                         ch = data[p];
1379                         if (ch == CR)
1380                         {
1381                             _state = HTTPParserState.s_header_almost_done;
1382                              _headerState = h_state;
1383                             mixin(CALLBACK_DATA("HeaderValue"));
1384                             break;
1385                         }
1386 
1387                         if (ch == LF)
1388                         {
1389                             _state = HTTPParserState.s_header_almost_done;
1390                             //COUNT_HEADER_SIZE(p - start);
1391                             _nread += (p - start);
1392                             if (_nread > _maxHeaderSize)
1393                             {
1394                                 _httpErrno = HTTPParserErrno.HPE_HEADER_OVERFLOW;
1395                                 goto error;
1396                             }
1397                              _headerState = h_state;
1398                             mixin(CALLBACK_DATA_NOADVANCE("HeaderValue"));
1399                             goto reexecute;
1400                         }
1401 
1402                         if (!_lenientHttpHeaders && !(ch == CR || ch == LF
1403                                 || ch == 9 || (ch > 31 && ch != 127)))
1404                         {
1405                             _httpErrno = HTTPParserErrno.HPE_INVALID_HEADER_TOKEN;
1406                             goto error;
1407                         }
1408 
1409                         c = ch | 0x20; //LOWER(ch);
1410 
1411                         switch (h_state)
1412                         {
1413                         case HTTPParserHeaderstates.h_general:
1414                             {
1415                                 import std.string;
1416                                 import core.stdc.string;
1417 
1418                                 size_t limit = maxP - p;
1419 
1420                                 limit = (limit < _maxHeaderSize ? limit : _maxHeaderSize); //MIN(limit, TTPConfig.instance.MaxHeaderSize);
1421                                 auto str =  data[p .. maxP];
1422                                 auto tptr = cast(ubyte *)memchr(str.ptr, CR, str.length);
1423                                 auto p_cr = tptr - str.ptr;//str._indexOf(CR); // memchr(p, CR, limit);
1424                                 tptr = cast(ubyte *)memchr(str.ptr, LF, str.length);
1425                                 auto p_lf = tptr - str.ptr ;//str._indexOf(LF); // memchr(p, LF, limit);
1426                                 ++p_cr;
1427                                 ++p_lf;
1428                                 if (p_cr > 0)
1429                                 {
1430                                     if (p_lf > 0 && p_cr >= p_lf)
1431                                         p += p_lf;
1432                                     else
1433                                         p += p_cr;
1434                                 }
1435                                 else if (p_lf > 0)
1436                                 {
1437                                     p += p_lf;
1438                                 }
1439                                 else
1440                                 {
1441                                     p = maxP;
1442                                 }
1443                                 p -= 2;
1444 
1445                                 break;
1446                             }
1447 
1448                         case HTTPParserHeaderstates.h_connection:
1449                         case HTTPParserHeaderstates.h_transfer_encoding:
1450                             assert(0,
1451                                 "Shouldn't get here.");
1452                             //break;
1453 
1454                         case HTTPParserHeaderstates.h_content_length:
1455                             {
1456                                 ulong t;
1457 
1458                                 if (ch == ' ')
1459                                     break;
1460 
1461                                 if (!mixin(IS_NUM("ch")))
1462                                 {
1463                                     _httpErrno = HTTPParserErrno.HPE_INVALID_CONTENT_LENGTH;
1464                                      _headerState = h_state;
1465                                     goto error;
1466                                 }
1467 
1468                                 t = _contentLength;
1469                                 t *= 10;
1470                                 t += ch - '0';
1471 
1472                                 /* Overflow? Test against a conservative limit for simplicity. */
1473                                 if ((ulong.max - 10) / 10 < _contentLength)
1474                                 {
1475                                     _httpErrno = HTTPParserErrno.HPE_INVALID_CONTENT_LENGTH;
1476                                      _headerState = h_state;
1477                                     goto error;
1478                                 }
1479 
1480                                 _contentLength = t;
1481                                 break;
1482                             }
1483 
1484                             /* Transfer-Encoding: chunked */
1485                         case HTTPParserHeaderstates.h_matching_transfer_encoding_chunked:
1486                             _index++;
1487                             if (_index > CHUNKED.length || c != CHUNKED[_index])
1488                             {
1489                                 h_state = HTTPParserHeaderstates.h_general;
1490                             }
1491                             else if (_index == CHUNKED.length - 1)
1492                             {
1493                                 h_state = HTTPParserHeaderstates.h_transfer_encoding_chunked;
1494                             }
1495                             break;
1496 
1497                         case HTTPParserHeaderstates.h_matching_connection_token_start:
1498                             /* looking for 'Connection: keep-alive' */
1499                             if (c == 'k')
1500                             {
1501                                 h_state = HTTPParserHeaderstates.h_matching_connection_keep_alive;
1502                                 /* looking for 'Connection: close' */
1503                             }
1504                             else if (c == 'c')
1505                             {
1506                                 h_state = HTTPParserHeaderstates.h_matching_connection_close;
1507                             }
1508                             else if (c == 'u')
1509                             {
1510                                 h_state = HTTPParserHeaderstates.h_matching_connection_upgrade;
1511                             }
1512                             else if (tokens[c])
1513                             {
1514                                 h_state = HTTPParserHeaderstates.h_matching_connection_token;
1515                             }
1516                             else if (c == ' ' || c == '\t')
1517                             {
1518                                 /* Skip lws */
1519                             }
1520                             else
1521                             {
1522                                 h_state = HTTPParserHeaderstates.h_general;
1523                             }
1524                             break;
1525 
1526                             /* looking for 'Connection: keep-alive' */
1527                         case HTTPParserHeaderstates.h_matching_connection_keep_alive:
1528                             _index++;
1529                             if (_index > KEEP_ALIVE.length || c != KEEP_ALIVE[_index])
1530                             {
1531                                 h_state = HTTPParserHeaderstates.h_matching_connection_token;
1532                             }
1533                             else if (_index == KEEP_ALIVE.length - 1)
1534                             {
1535                                 h_state = HTTPParserHeaderstates.h_connection_keep_alive;
1536                             }
1537                             break;
1538 
1539                             /* looking for 'Connection: close' */
1540                         case HTTPParserHeaderstates.h_matching_connection_close:
1541                             _index++;
1542                             if (_index > CLOSE.length || c != CLOSE[_index])
1543                             {
1544                                 h_state = HTTPParserHeaderstates.h_matching_connection_token;
1545                             }
1546                             else if (_index == CLOSE.length - 1)
1547                             {
1548                                 h_state = HTTPParserHeaderstates.h_connection_close;
1549                             }
1550                             break;
1551 
1552                             /* looking for 'Connection: upgrade' */
1553                         case HTTPParserHeaderstates.h_matching_connection_upgrade:
1554                             _index++;
1555                             if (_index > UPGRADE.length || c != UPGRADE[_index])
1556                             {
1557                                 h_state = HTTPParserHeaderstates.h_matching_connection_token;
1558                             }
1559                             else if (_index == UPGRADE.length - 1)
1560                             {
1561                                 h_state = HTTPParserHeaderstates.h_connection_upgrade;
1562                             }
1563                             break;
1564 
1565                         case HTTPParserHeaderstates.h_matching_connection_token:
1566                             if (ch == ',')
1567                             {
1568                                 h_state = HTTPParserHeaderstates.h_matching_connection_token_start;
1569                                 _index = 0;
1570                             }
1571                             break;
1572 
1573                         case HTTPParserHeaderstates.h_transfer_encoding_chunked:
1574                             if (
1575                                     ch != ' ')
1576                                 h_state = HTTPParserHeaderstates.h_general;
1577                             break;
1578 
1579                         case HTTPParserHeaderstates.h_connection_keep_alive:
1580                         case HTTPParserHeaderstates.h_connection_close:
1581                         case HTTPParserHeaderstates.h_connection_upgrade:
1582                             if (ch == ',')
1583                             {
1584                                 if (h_state == HTTPParserHeaderstates.h_connection_keep_alive)
1585                                 {
1586                                     _flags |= HTTPParserFlags.F_CONNECTION_KEEP_ALIVE;
1587                                 }
1588                                 else if (h_state == HTTPParserHeaderstates.h_connection_close)
1589                                 {
1590                                     _flags |= HTTPParserFlags.F_CONNECTION_CLOSE;
1591                                 }
1592                                 else if (h_state == HTTPParserHeaderstates.h_connection_upgrade)
1593                                 {
1594                                     _flags |= HTTPParserFlags.F_CONNECTION_UPGRADE;
1595                                 }
1596                                 h_state = HTTPParserHeaderstates.h_matching_connection_token_start;
1597                                 _index = 0;
1598                             }
1599                             else if (ch != ' ')
1600                             {
1601                                 h_state = HTTPParserHeaderstates.h_matching_connection_token;
1602                             }
1603                             break;
1604 
1605                         default:
1606                             _state = HTTPParserState.s_header_value;
1607                             h_state = HTTPParserHeaderstates.h_general;
1608                             break;
1609                         }
1610                     }
1611 
1612                      _headerState = h_state;
1613 
1614                     //COUNT_HEADER_SIZE(p - start);
1615                     _nread += (p - start);
1616                     if (_nread > _maxHeaderSize)
1617                     {
1618                         _httpErrno = HTTPParserErrno.HPE_HEADER_OVERFLOW;
1619                         goto error;
1620                     }
1621 
1622                     if (p == maxP)
1623                         --p;
1624                     break;
1625                 }
1626 
1627             case HTTPParserState.s_header_almost_done:
1628                 {
1629                     if (ch != LF)
1630                     {
1631                         _httpErrno = HTTPParserErrno.HPE_LF_EXPECTED;
1632                         goto error;
1633                     }
1634 
1635                     _state = HTTPParserState.s_header_value_lws;
1636                     break;
1637                 }
1638 
1639             case HTTPParserState.s_header_value_lws:
1640                 {
1641                     if (ch == ' ' || ch == '\t')
1642                     {
1643                         _state = HTTPParserState.s_header_value_start;
1644                         goto reexecute;
1645                     }
1646 
1647                     /* finished the header */
1648                     switch ( _headerState)
1649                     {
1650                     case HTTPParserHeaderstates.h_connection_keep_alive:
1651                         _flags |= HTTPParserFlags.F_CONNECTION_KEEP_ALIVE;
1652                         break;
1653                     case HTTPParserHeaderstates.h_connection_close:
1654                         _flags |= HTTPParserFlags.F_CONNECTION_CLOSE;
1655                         break;
1656                     case HTTPParserHeaderstates.h_transfer_encoding_chunked:
1657                         _flags |= HTTPParserFlags.F_CHUNKED;
1658                         break;
1659                     case HTTPParserHeaderstates.h_connection_upgrade:
1660                         _flags |= HTTPParserFlags.F_CONNECTION_UPGRADE;
1661                         break;
1662                     default:
1663                         break;
1664                     }
1665 
1666                     _state = HTTPParserState.s_header_field_start;
1667                     goto reexecute;
1668                 }
1669 
1670             case HTTPParserState.s_header_value_discard_ws_almost_done:
1671                 {
1672                     mixin(STRICT_CHECK("ch != LF"));
1673                     _state = HTTPParserState.s_header_value_discard_lws;
1674                     break;
1675                 }
1676 
1677             case HTTPParserState.s_header_value_discard_lws:
1678                 {
1679                     if (ch == ' ' || ch == '\t')
1680                     {
1681                         _state = HTTPParserState.s_header_value_discard_ws;
1682                         break;
1683                     }
1684                     else
1685                     {
1686                         switch ( _headerState)
1687                         {
1688                         case HTTPParserHeaderstates.h_connection_keep_alive:
1689                             _flags |= HTTPParserFlags.F_CONNECTION_KEEP_ALIVE;
1690                             break;
1691                         case HTTPParserHeaderstates.h_connection_close:
1692                             _flags |= HTTPParserFlags.F_CONNECTION_CLOSE;
1693                             break;
1694                         case HTTPParserHeaderstates.h_connection_upgrade:
1695                             _flags |= HTTPParserFlags.F_CONNECTION_UPGRADE;
1696                             break;
1697                         case HTTPParserHeaderstates.h_transfer_encoding_chunked:
1698                             _flags |= HTTPParserFlags.F_CHUNKED;
1699                             break;
1700                         default:
1701                             break;
1702                         }
1703 
1704                         /* header value was empty */
1705                         //MARK(header_value);
1706                         if (mHeaderValueMark == size_t.max)
1707                         {
1708                             mHeaderValueMark = p;
1709                         }
1710                         _state = HTTPParserState.s_header_field_start;
1711                         mixin(CALLBACK_DATA_NOADVANCE("HeaderValue"));
1712                         goto reexecute;
1713                     }
1714                 }
1715                 //TODO	
1716             case HTTPParserState.s_headers_almost_done:
1717                 {
1718                     mixin(STRICT_CHECK("ch != LF"));
1719 
1720                     if (_flags & HTTPParserFlags.F_TRAILING)
1721                     {
1722                         /* End of a chunked request */
1723                         _state = HTTPParserState.s_message_done;
1724                         mixin(CALLBACK_NOTIFY_NOADVANCE("ChunkComplete"));
1725                         goto reexecute;
1726                     }
1727 
1728                     /* Cannot use chunked encoding and a content-length header together
1729 					 per the HTTP specification. */
1730                     if ((_flags & HTTPParserFlags.F_CHUNKED)
1731                             && (_flags & HTTPParserFlags.F_CONTENTLENGTH))
1732                     {
1733                         _httpErrno = HTTPParserErrno.HPE_UNEXPECTED_CONTENT_LENGTH;
1734                         goto error;
1735                     }
1736 
1737                     _state = HTTPParserState.s_headers_done;
1738 
1739                     /* Set this here so that on_headers_complete() callbacks can see it */
1740                     _upgrade = (
1741                         (_flags & (HTTPParserFlags.F_UPGRADE | HTTPParserFlags.F_CONNECTION_UPGRADE)) == (
1742                         HTTPParserFlags.F_UPGRADE | HTTPParserFlags.F_CONNECTION_UPGRADE)
1743                         || _method == HTTPMethod.HTTP_CONNECT);
1744                     {
1745 						if(_keepAlive == 0x00 && _httpMinor == 0 && _httpMajor == 1){
1746 							_keepAlive = 0x02;
1747 						}else {
1748 							_keepAlive = 0x01;
1749 						}
1750                         if (_onHeadersComplete !is null)
1751                         {
1752                             _onHeadersComplete(this);
1753                             //error("_onHeadersComplete " , errorString);
1754                             //error("handleIng  " , handleIng);
1755                             //error("handleIng  " , skipBody);
1756                             //error("state  " , state);
1757                             if (!handleIng)
1758                             {
1759                                 _httpErrno = HTTPParserErrno.HPE_CB_HeadersComplete;
1760                                 return p; /* Error */
1761                             }
1762                             if (skipBody)
1763                                 _flags |= HTTPParserFlags.F_SKIPBODY;
1764 
1765                         }
1766 
1767                     }
1768 
1769                     goto reexecute;
1770                 }
1771 
1772             case HTTPParserState.s_headers_done:
1773                 {
1774                     int hasBody;
1775                     mixin(STRICT_CHECK("ch != LF"));
1776 
1777                     _nread = 0;
1778                     //int chunked = _flags & HTTPParserFlags.F_CHUNKED ;
1779                     //error("s_headers_done is chunked : ", chunked);
1780                     hasBody = _flags & HTTPParserFlags.F_CHUNKED
1781                         || (_contentLength > 0 && _contentLength != ULLONG_MAX);
1782                     if (_upgrade && (_method == HTTPMethod.HTTP_CONNECT
1783                             || (_flags & HTTPParserFlags.F_SKIPBODY) || !hasBody))
1784                     {
1785                         /* Exit, the rest of the message is in a different protocol. */
1786                         _state = mixin(NEW_MESSAGE);
1787                         mixin(CALLBACK_NOTIFY("MessageComplete"));
1788                         return (p + 1);
1789                     }
1790 
1791                     if (_flags & HTTPParserFlags.F_SKIPBODY)
1792                     {
1793                         _state = mixin(NEW_MESSAGE);
1794 						mixin(CALLBACK_NOTIFY("MessageComplete"));
1795                     }
1796                     else if (_flags & HTTPParserFlags.F_CHUNKED)
1797                     {
1798                         /* chunked encoding - ignore Content-Length header */
1799                         _state = HTTPParserState.s_chunk_size_start;
1800                     }
1801                     else
1802                     {
1803                         if (_contentLength == 0)
1804                         {
1805                             /* Content-Length header given but zero: Content-Length: 0\r\n */
1806                             _state = mixin(NEW_MESSAGE);
1807 							mixin(CALLBACK_NOTIFY("MessageComplete"));
1808                         }
1809                         else if (_contentLength != ULLONG_MAX)
1810                         {
1811                             /* Content-Length header given and non-zero */
1812                             _state = HTTPParserState.s_body_identity;
1813                         }
1814                         else
1815                         {
1816                             if (!httpMessageNeedsEof())
1817                             {
1818                                 /* Assume content-length 0 - read the next */
1819                                 _state = mixin(NEW_MESSAGE);
1820 								mixin(CALLBACK_NOTIFY("MessageComplete"));
1821                             }
1822                             else
1823                             {
1824                                 /* Read body until EOF */
1825                                 _state = HTTPParserState.s_body_identity_eof;
1826                             }
1827                         }
1828                     }
1829 
1830                     break;
1831                 }
1832 
1833             case HTTPParserState.s_body_identity:
1834                 {
1835                     ulong to_read = _contentLength < cast(ulong)(maxP - p) ? _contentLength : cast(
1836                         ulong)(maxP - p);
1837 
1838                     assert(_contentLength != 0 && _contentLength != ULLONG_MAX);
1839 
1840                     /* The difference between advancing _contentLength and p is because
1841 					 * the latter will automaticaly advance on the next loop iteration.
1842 					 * Further, if _contentLength ends up at 0, we want to see the last
1843 					 * byte again for our message complete callback.
1844 					 */
1845                     //MARK(body);
1846 
1847                     if (mBodyMark == size_t.max)
1848                     {
1849                         mBodyMark = p;
1850                     }
1851                     _contentLength -= to_read;
1852                     p += to_read - 1;
1853 
1854                     if (_contentLength == 0)
1855                     {
1856                         _state = HTTPParserState.s_message_done;
1857 
1858                         /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1859 						 *
1860 						 * The alternative to doing this is to wait for the next byte to
1861 						 * trigger the data callback, just as in every other case. The
1862 						 * problem with this is that this makes it difficult for the test
1863 						 * harness to distinguish between complete-on-EOF and
1864 						 * complete-on-length. It's not clear that this distinction is
1865 						 * important for applications, but let's keep it for now.
1866 						 */
1867                         if (mBodyMark != size_t.max && _onBody !is null)
1868                         {
1869                             ubyte[] _data = data[mBodyMark .. p + 1];
1870                             _onBody(this, _data, true);
1871                             if (!handleIng)
1872                             {
1873                                 _httpErrno = HTTPParserErrno.HPE_CB_Body;
1874                                 return p + 1;
1875                             }
1876                         }
1877                         mBodyMark = size_t.max;
1878                         goto reexecute;
1879                     }
1880 
1881                     break;
1882                 }
1883 
1884                 /* read until EOF */
1885             case HTTPParserState.s_body_identity_eof:
1886                 //MARK(body);
1887                 if (mBodyMark == size_t.max)
1888                 {
1889                     mBodyMark = p;
1890                 }
1891 
1892                 p = maxP - 1;
1893 
1894                 break;
1895 
1896             case HTTPParserState.s_message_done:
1897                 _state = mixin(NEW_MESSAGE);
1898 				mixin(CALLBACK_NOTIFY("MessageComplete"));
1899                 if (_upgrade)
1900                 {
1901                     /* Exit, the rest of the message is in a different protocol. */
1902                     return (p + 1);
1903                 }
1904                 break;
1905 
1906             case HTTPParserState.s_chunk_size_start:
1907                 {
1908                     assert(_nread == 1);
1909                     assert(_flags & HTTPParserFlags.F_CHUNKED);
1910 
1911                     unhexVal = unhex[ch];
1912                     if (unhexVal == -1)
1913                     {
1914                         _httpErrno = HTTPParserErrno.HPE_INVALID_CHUNK_SIZE;
1915                         goto error;
1916                     }
1917 
1918                     _contentLength = unhexVal;
1919                     _state = HTTPParserState.s_chunk_size;
1920                     break;
1921                 }
1922 
1923             case HTTPParserState.s_chunk_size:
1924                 {
1925                     ulong t;
1926 
1927                     assert(_flags & HTTPParserFlags.F_CHUNKED);
1928 
1929                     if (ch == CR)
1930                     {
1931                         _state = HTTPParserState.s_chunk_size_almost_done;
1932                         break;
1933                     }
1934 
1935                     unhexVal = unhex[ch];
1936 
1937                     if (unhexVal == -1)
1938                     {
1939                         if (ch == ';' || ch == ' ')
1940                         {
1941                             _state = HTTPParserState.s_chunk_parameters;
1942                             break;
1943                         }
1944 
1945                         _httpErrno = HTTPParserErrno.HPE_INVALID_CHUNK_SIZE;
1946                         goto error;
1947                     }
1948 
1949                     t = _contentLength;
1950                     t *= 16;
1951                     t += unhexVal;
1952 
1953                     /* Overflow? Test against a conservative limit for simplicity. */
1954                     if ((ULLONG_MAX - 16) / 16 < _contentLength)
1955                     {
1956                         _httpErrno = HTTPParserErrno.HPE_INVALID_CONTENT_LENGTH;
1957                         goto error;
1958                     }
1959 
1960                     _contentLength = t;
1961                     break;
1962                 }
1963 
1964             case HTTPParserState.s_chunk_parameters:
1965                 {
1966                     assert(_flags & HTTPParserFlags.F_CHUNKED);
1967                     /* just ignore this shit. TODO check for overflow */
1968                     if (ch == CR)
1969                     {
1970                         _state = HTTPParserState.s_chunk_size_almost_done;
1971                         break;
1972                     }
1973                     break;
1974                 }
1975 
1976             case HTTPParserState.s_chunk_size_almost_done:
1977                 {
1978                     assert(_flags & HTTPParserFlags.F_CHUNKED);
1979                     mixin(STRICT_CHECK("ch != LF"));
1980 
1981                     _nread = 0;
1982 
1983                     if (_contentLength == 0)
1984                     {
1985                         _flags |= HTTPParserFlags.F_TRAILING;
1986                         _state = HTTPParserState.s_header_field_start;
1987                     }
1988                     else
1989                     {
1990                         _state = HTTPParserState.s_chunk_data;
1991                     }
1992                     mixin(CALLBACK_NOTIFY("ChunkHeader"));
1993                     break;
1994                 }
1995 
1996             case HTTPParserState.s_chunk_data:
1997                 {
1998                     ulong to_read = _contentLength < cast(ulong)(maxP - p) ? _contentLength : cast(
1999                         ulong)(maxP - p);
2000 
2001                     assert(_flags & HTTPParserFlags.F_CHUNKED);
2002                     assert(_contentLength != 0 && _contentLength != ULLONG_MAX);
2003 
2004                     /* See the explanation in s_body_identity for why the content
2005 					 * length and data pointers are managed this way.
2006 					 */
2007                     //MARK(body);
2008                     if (mBodyMark == size_t.max)
2009                     {
2010                         mBodyMark = p;
2011                     }
2012                     _contentLength -= to_read;
2013                     p += to_read - 1;
2014 
2015                     if (_contentLength == 0)
2016                     {
2017                         _state = HTTPParserState.s_chunk_data_almost_done;
2018                     }
2019 
2020                     break;
2021                 }
2022 
2023             case HTTPParserState.s_chunk_data_almost_done:
2024                 assert(_flags & HTTPParserFlags.F_CHUNKED);
2025                 assert(_contentLength == 0);
2026                 mixin(STRICT_CHECK("ch != CR"));
2027                 _state = HTTPParserState.s_chunk_data_done;
2028                 mixin(CALLBACK_DATA("Body"));
2029                 break;
2030 
2031             case HTTPParserState.s_chunk_data_done:
2032                 assert(_flags & HTTPParserFlags.F_CHUNKED);
2033                 mixin(STRICT_CHECK("ch != LF"));
2034                 _nread = 0;
2035                 _state = HTTPParserState.s_chunk_size_start;
2036                 mixin(CALLBACK_NOTIFY("ChunkComplete"));
2037                 break;
2038 
2039             default:
2040                 //assert(0 && "unhandled state");
2041                 _httpErrno = HTTPParserErrno.HPE_INVALID_INTERNAL_STATE;
2042                 goto error;
2043             }
2044         }
2045 
2046         assert(
2047             (
2048             (mHeaderFieldMark != size_t.max ? 1 : 0) + (mHeaderValueMark != size_t.max ? 1 : 0) + (
2049             mUrlMark != size_t.max ? 1 : 0) + (mBodyMark != size_t.max ? 1 : 0) + (
2050             mStatusMark != size_t.max ? 1 : 0)) <= 1);
2051 
2052         mixin(CALLBACK_DATA_NOADVANCE("HeaderField")); //最后没找到
2053         mixin(CALLBACK_DATA_NOADVANCE("HeaderValue"));
2054         mixin(CALLBACK_DATA_NOADVANCE("Url"));
2055         mixin(CALLBACK_DATA_NOADVANCE("Body"));
2056         mixin(CALLBACK_DATA_NOADVANCE("Status"));
2057 
2058         return data.length;
2059 
2060     error:
2061         if (_httpErrno == HTTPParserErrno.HPE_OK)
2062         {
2063             _httpErrno = HTTPParserErrno.HPE_UNKNOWN;
2064         }
2065 
2066         return p;
2067     }
2068 
2069 private:
2070     HTTPParserType _type = HTTPParserType.HTTP_BOTH;
2071     HTTPParserFlags _flags = HTTPParserFlags.F_ZERO;
2072 	HTTPParserState _state = HTTPParserState.s_start_req_or_res;
2073     HTTPParserHeaderstates  _headerState;
2074     uint _index;
2075     uint _lenientHttpHeaders;
2076     uint _nread;
2077     ulong _contentLength;
2078     ushort _httpMajor;
2079     ushort _httpMinor;
2080     uint _statusCode; /* responses only */
2081     HTTPMethod _method; /* requests only */
2082     HTTPParserErrno _httpErrno = HTTPParserErrno.HPE_OK;
2083     /* 1 = Upgrade header was present and the parser has exited because of that.
2084 	 * 0 = No upgrade header present.
2085 	 * Should be checked when http_parser_execute() returns in addition to
2086 	 * error checking.
2087 	 */
2088     bool _upgrade;
2089 
2090     bool _isHandle = false;
2091 
2092     bool _skipBody = false;
2093 
2094 	ubyte _keepAlive = 0x00;
2095 
2096     uint _maxHeaderSize = 4096;
2097 
2098 protected:
2099     @property type(HTTPParserType ty)
2100     {
2101         _type = ty;
2102     }
2103 
2104     pragma(inline)
2105     bool httpMessageNeedsEof()
2106     {
2107         if (type == HTTPParserType.HTTP_REQUEST)
2108         {
2109             return false;
2110         }
2111 
2112         /* See RFC 2616 section 4.4 */
2113         if (_statusCode / 100 == 1 || /* 1xx e.g. Continue */
2114                 _statusCode == 204 || /* No Content */
2115                 _statusCode == 304
2116                 || /* Not Modified */
2117                 _flags & HTTPParserFlags.F_SKIPBODY)
2118         { /* response to a HEAD request */
2119             return false;
2120         }
2121 
2122         if ((_flags & HTTPParserFlags.F_CHUNKED) || _contentLength != ULLONG_MAX)
2123         {
2124             return false;
2125         }
2126 
2127         return true;
2128     }
2129 
2130     pragma(inline)
2131     bool httpShouldKeepAlive()
2132     {
2133         if (_httpMajor > 0 && _httpMinor > 0)
2134         {
2135             /* HTTP/1.1 */
2136             if (_flags & HTTPParserFlags.F_CONNECTION_CLOSE)
2137             {
2138                 return false;
2139             }
2140         }
2141         else
2142         {
2143             /* HTTP/1.0 or earlier */
2144             if (!(_flags & HTTPParserFlags.F_CONNECTION_KEEP_ALIVE))
2145             {
2146                 return false;
2147             }
2148         }
2149 
2150         return !httpMessageNeedsEof();
2151     }
2152 
2153     HTTPParserState parseURLchar(HTTPParserState s, ubyte ch)
2154     {
2155         if (ch == ' ' || ch == '\r' || ch == '\n')
2156         {
2157             return HTTPParserState.s_dead;
2158         }
2159 
2160         version (HTTP_PARSER_STRICT)
2161         {
2162             if (ch == '\t' || ch == '\f')
2163             {
2164                 return s_dead;
2165             }
2166         }
2167 
2168         switch (s)
2169         {
2170         case HTTPParserState.s_req_spaces_before_url:
2171             /* Proxied requests are followed by scheme of an absolute URI (alpha).
2172 				 * All methods except CONNECT are followed by '/' or '*'.
2173 				 */
2174 
2175             if (ch == '/' || ch == '*')
2176             {
2177                 return HTTPParserState.s_req_path;
2178             }
2179 
2180             if (mixin(IS_ALPHA("ch")))
2181             {
2182                 return HTTPParserState.s_req_schema;
2183             }
2184 
2185             break;
2186 
2187         case HTTPParserState.s_req_schema:
2188             if (mixin(IS_ALPHA("ch")))
2189             {
2190                 return s;
2191             }
2192 
2193             if (ch == ':')
2194             {
2195                 return HTTPParserState.s_req_schema_slash;
2196             }
2197 
2198             break;
2199 
2200         case HTTPParserState.s_req_schema_slash:
2201             if (ch == '/')
2202             {
2203                 return HTTPParserState.s_req_schema_slash_slash;
2204             }
2205 
2206             break;
2207 
2208         case HTTPParserState.s_req_schema_slash_slash:
2209             if (ch == '/')
2210             {
2211                 return HTTPParserState.s_req_server_start;
2212             }
2213 
2214             break;
2215 
2216         case HTTPParserState.s_req_server_with_at:
2217             if (ch == '@')
2218             {
2219                 return HTTPParserState.s_dead;
2220             }
2221             goto case;
2222             /* FALLTHROUGH */
2223         case HTTPParserState.s_req_server_start:
2224         case HTTPParserState.s_req_server:
2225             {
2226                 if (ch == '/')
2227                 {
2228                     return HTTPParserState.s_req_path;
2229                 }
2230 
2231                 if (ch == '?')
2232                 {
2233                     return HTTPParserState.s_req_query_string_start;
2234                 }
2235 
2236                 if (ch == '@')
2237                 {
2238                     return HTTPParserState.s_req_server_with_at;
2239                 }
2240 
2241                 if (IS_USERINFO_CHAR2(ch) || ch == '[' || ch == ']')
2242                 {
2243                     return HTTPParserState.s_req_server;
2244                 }
2245             }
2246             break;
2247 
2248         case HTTPParserState.s_req_path:
2249             {
2250                 if (mixin(IS_URL_CHAR("ch")))
2251                 {
2252                     return s;
2253                 }
2254 
2255                 switch (ch)
2256                 {
2257                 case '?':
2258                     return HTTPParserState.s_req_query_string_start;
2259 
2260                 case '#':
2261                     return HTTPParserState.s_req_fragment_start;
2262                 default:
2263                     break;
2264                 }
2265                 break;
2266             }
2267 
2268         case HTTPParserState.s_req_query_string_start:
2269         case HTTPParserState.s_req_query_string:
2270             {
2271                 if (mixin(IS_URL_CHAR("ch")))
2272                 {
2273                     return HTTPParserState.s_req_query_string;
2274                 }
2275 
2276                 switch (ch)
2277                 {
2278                 case '?':
2279                     /* allow extra '?' in query string */
2280                     return HTTPParserState.s_req_query_string;
2281 
2282                 case '#':
2283                     return HTTPParserState.s_req_fragment_start;
2284                 default:
2285                     break;
2286                 }
2287                 break;
2288             }
2289 
2290         case HTTPParserState.s_req_fragment_start:
2291             {
2292                 if (mixin(IS_URL_CHAR("ch")))
2293                 {
2294                     return HTTPParserState.s_req_fragment;
2295                 }
2296 
2297                 switch (ch)
2298                 {
2299                 case '?':
2300                     return HTTPParserState.s_req_fragment;
2301 
2302                 case '#':
2303                     return s;
2304                 default:
2305                     break;
2306                 }
2307                 break;
2308             }
2309 
2310         case HTTPParserState.s_req_fragment:
2311             {
2312                 if (mixin(IS_URL_CHAR("ch")))
2313                 {
2314                     return s;
2315                 }
2316 
2317                 switch (ch)
2318                 {
2319                 case '?':
2320                 case '#':
2321                     return s;
2322                 default:
2323                     break;
2324                 }
2325                 break;
2326             }
2327         default:
2328             break;
2329         }
2330 
2331         /* We should never fall out of the switch above unless there's an error */
2332         return HTTPParserState.s_dead;
2333     }
2334 
2335 }
2336 
2337 private:
2338 
2339 pragma(inline,true)
2340 bool IS_USERINFO_CHAR2(ubyte c)
2341 {
2342     bool alpha = mixin(IS_ALPHA("c"));
2343     bool sum = mixin(IS_NUM("c"));
2344     bool b1 = (c == '%' || c == ';' || c == ':' || c == '&' || c == '='
2345         || c == '+' || c == '$' || c == ',');
2346     bool b2 = (c == '-' || '_' == c || '.' == c || '!' == c || '~' == c || '*' == c
2347         || '\'' == c || '(' == c || ')' == c);
2348     return (b2 || b1 || sum || alpha);
2349 }
2350 
2351 string IS_USERINFO_CHAR(string c)
2352 {
2353     return "( " ~ IS_ALPHA(c) ~ " || " ~ IS_NUM(c) ~ " || " ~ c ~ " == '%' || " ~ c ~ " == ';' || " ~ c ~ " == ':' || " ~ c ~ " == '&' || " ~ c ~ " == '=' ||  " ~ c ~ " == '+' || " ~ c ~ " == '$' || " ~ c ~ " == ','" ~ c ~ " == '-' || '_' == " ~ c ~ "|| '.' == " ~ c ~ "|| '!' == " ~ c ~ "|| '~' == " ~ c ~ "|| '*' == " ~ c ~ "|| '\'' == " ~ c ~ "|| '(' == " ~ c ~ "|| ')' == " ~ c ~ ")";
2354 }
2355 
2356 string STRICT_CHECK(string cond)
2357 {
2358     string code = "if (";
2359     code = code ~ cond ~ ") {                                                   
2360 			_httpErrno = HTTPParserErrno.HPE_STRICT;                                     
2361 			goto error;                                           
2362 		}  ";
2363     return code;
2364 }
2365 
2366 //	string IS_MARK(string c) { return "(" ~ c ~ " == '-' || " ~ c ~ " == '_' || "~ c ~ " == '.' || " ~ c ~ " == '!' || " ~ c ~ " == '~' ||  " ~ c ~ " == '*' ||  " ~ c ~ " == '\'' || " ~ c ~ " == '(' || " ~ c ~ " == ')')";}
2367 string IS_NUM(string c)
2368 {
2369     return "(" ~ c ~ " >= '0' &&  " ~ c ~ "  <= '9')";
2370 }
2371 
2372 string IS_ALPHA(string c)
2373 {
2374     return "((" ~ c ~ "| 0x20) >= 'a' && (" ~ c ~ " | 0x20) <= 'z')";
2375 }
2376 
2377 string IS_URL_CHAR(string c)
2378 {
2379     return "(!!(cast(uint) (normal_url_char[cast(uint) (" ~ c ~ ") >> 3] ) &                  
2380 				(1 << (cast(uint)" ~ c ~ " & 7))))";
2381 }
2382 
2383 enum NEW_MESSAGE = "httpShouldKeepAlive() ? (type == HTTPParserType.HTTP_REQUEST ? HTTPParserState.s_start_req : HTTPParserState.s_start_res) : HTTPParserState.s_dead";
2384 string CALLBACK_NOTIFY(string code)
2385 {
2386     string _s = " {if (_on" ~ code ~ " !is null){
2387                _on" ~ code ~ "(this); if(!handleIng){
2388                 _httpErrno = HTTPParserErrno.HPE_CB_" ~ code ~ ";
2389                 return  p + 1;}} }";
2390     return _s;
2391 }
2392 
2393 string CALLBACK_NOTIFY_NOADVANCE(string code)
2394 {
2395     string _s = " {if (_on" ~ code ~ " != null){
2396 	               _on" ~ code ~ "(this); if(!handleIng){
2397 	                _httpErrno = HTTPParserErrno.HPE_CB_" ~ code ~ ";
2398 	                return  p;} }}";
2399     return _s;
2400 }
2401 
2402 string CALLBACK_DATA(string code)
2403 {
2404     string _s = "{ if( m" ~ code ~ "Mark != size_t.max && _on" ~ code ~ " !is null){
2405                 ulong len = (p - m" ~ code ~ "Mark) ;
2406                 
2407                 if(len > 0) {  
2408                /* writeln(\"CALLBACK_DATA at  \",__LINE__, \"  " ~ code ~ "\");*/
2409                 ubyte[]  _data =  data[m" ~ code ~ "Mark..p];
2410                 _on" ~ code ~ "(this,_data,true);
2411                 if (!handleIng){
2412                     _httpErrno = HTTPParserErrno.HPE_CB_" ~ code ~ ";
2413                     return  p + 1;}} } m" ~ code ~ "Mark = size_t.max;}";
2414     return _s;
2415 }
2416 
2417 string CALLBACK_DATA_NOADVANCE(string code)
2418 {
2419 	string _s = "{ if(m" ~ code ~ "Mark != size_t.max && _on" ~ code ~ " !is null){
2420                 ulong len = (p - m" ~ code ~ "Mark) ;
2421                 if(len > 0) {  
2422                  /*writeln(\"CALLBACK_DATA_NOADVANCE at  \",__LINE__, \"  " ~ code ~ "\");*/
2423                 ubyte[]  _data = data[m" ~ code ~ "Mark..p];
2424                 _on" ~ code ~ "(this,_data,false);
2425                 if (!handleIng){
2426                     _httpErrno = HTTPParserErrno.HPE_CB_" ~ code ~ ";
2427                 return  p;} }}m" ~ code ~ "Mark = size_t.max;}";
2428     return _s;
2429 }
2430 
2431 unittest
2432 {
2433     import std.stdio;
2434     import std.functional;
2435 
2436     writeln("\n\n\n");
2437 
2438     void on_message_begin(ref HTTPParser)
2439     {
2440         writeln("_onMessageBegin");
2441         writeln(" ");
2442     }
2443 
2444 	void on_url(ref HTTPParser par, ubyte[] data, bool adv)
2445     {
2446         writeln("_onUrl, is NOADVANCE = ", adv);
2447         writeln("\" ", cast(string) data, " \"");
2448         writeln("HTTPMethod is = ", par.methodString);
2449         writeln(" ");
2450     }
2451 
2452 	void on_status(ref HTTPParser par, ubyte[] data, bool adv)
2453     {
2454         writeln("_onStatus, is NOADVANCE = ", adv);
2455         writeln("\" ", cast(string) data, " \"");
2456         writeln(" ");
2457     }
2458 
2459 	void on_header_field(ref HTTPParser par, ubyte[] data, bool adv)
2460     {
2461         static bool frist = true;
2462         writeln("_onHeaderField, is NOADVANCE = ", adv);
2463         writeln("len = ", data.length);
2464         writeln("\" ", cast(string) data, " \"");
2465         if (frist)
2466         {
2467             writeln("\t _httpMajor", par.major);
2468             writeln("\t _httpMinor", par.minor);
2469             frist = false;
2470         }
2471         writeln(" ");
2472     }
2473 
2474 	void on_header_value(ref HTTPParser par, ubyte[] data, bool adv)
2475     {
2476         writeln("_onHeaderValue, is NOADVANCE = ", adv);
2477         writeln("\" ", cast(string) data, " \"");
2478         writeln(" ");
2479     }
2480 
2481 	void on_headers_complete(ref HTTPParser par)
2482     {
2483         writeln("_onHeadersComplete");
2484         writeln(" ");
2485     }
2486 
2487 	void on_body(ref HTTPParser par, ubyte[] data, bool adv)
2488     {
2489         writeln("_onBody, is NOADVANCE = ", adv);
2490         writeln("\" ", cast(string) data, " \"");
2491         writeln(" ");
2492     }
2493 
2494 	void on_message_complete(ref HTTPParser par)
2495     {
2496         writeln("_onMessageComplete");
2497         writeln(" ");
2498     }
2499 
2500 	void on_chunk_header(ref HTTPParser par)
2501     {
2502         writeln("_onChunkHeader");
2503         writeln(" ");
2504     }
2505 
2506 	void on_chunk_complete(ref HTTPParser par)
2507     {
2508         writeln("_onChunkComplete");
2509         writeln(" ");
2510     }
2511 
2512     string data = "GET /test HTTP/1.1\r\nUser-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\nHost:0.0.0.0=5000\r\nAccept: */*\r\n\r\n";
2513     HTTPParser par = HTTPParser();
2514     par.onMessageBegin = toDelegate(&on_message_begin);
2515     par.onMessageComplete = toDelegate(&on_message_complete);
2516     par.onUrl = toDelegate(&on_url);
2517     par.onStatus = toDelegate(&on_status);
2518     par.onHeaderField = toDelegate(&on_header_field);
2519     par.onHeaderValue = toDelegate(&on_header_value);
2520     par.onChunkHeader = toDelegate(&on_chunk_header);
2521     par.onChunkComplete = toDelegate(&on_chunk_complete);
2522     par.onBody = toDelegate(&on_body);
2523 
2524     ulong len = par.httpParserExecute(cast(ubyte[]) data);
2525     if (data.length != len)
2526     {
2527         writeln("\t error ! ", par.error);
2528     }
2529     par.rest(HTTPParserType.HTTP_BOTH);
2530     data = "POST /post_chunked_all_your_base HTTP/1.1\r\nHost:0.0.0.0=5000\r\nTransfer-Encoding:chunked\r\n\r\n5\r\nhello\r\n";
2531 
2532     auto data2 = "0\r\n\r\n";
2533 
2534     len = par.httpParserExecute(cast(ubyte[]) data);
2535     if (data.length != len)
2536     {
2537         writeln("error1 ! ", par.error);
2538         writeln("\t error1 ! ", par.errorString);
2539         return;
2540     }
2541     writeln("data 1 is over!");
2542     len = par.httpParserExecute(cast(ubyte[]) data2);
2543     writeln("last len = ", len);
2544     if (data2.length != len)
2545     {
2546         writeln("\t error ! ", par.errorString);
2547         writeln("HTTPMethod is = ", par.methodString);
2548         writeln("erro!!!!!");
2549     }
2550 }