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