private HttpParserSettings SetupParserSettings() { return(new HttpParserSettings { OnMessageBegin = parserPtr => { _handler.OnMessageBegin(); return 0; }, OnStatus = (parserPtr, statusPtr, lengthPtr) => { _handler.OnStatus(GetAsciiString(statusPtr, lengthPtr)); return 0; }, OnHeadersComplete = parserPtr => { _handler.OnHeadersComplete(); return 0; }, OnBody = (parserPtr, bodyPtr, lengthPtr) => { var bodyOffset = GetBodyOffset(bodyPtr, ref _bufferPinPtr); var bodyParsedLength = (int)lengthPtr.ToUInt32(); _handler.OnBody(GetBodyArraySegment(ref _buffer, bodyOffset, bodyParsedLength)); return 0; }, OnMessageComplete = parserPtr => { _handler.OnMessageComplete(); return 0; } }); }
public int Execute(ArraySegment <byte> buf) { byte[] data = buf.Array; int p = buf.Offset; int pe = buf.Offset + buf.Count; int eof = buf.Count == 0 ? buf.Offset : -1; //int eof = pe; // mark = 0; //if (p == pe) // Console.WriteLine("Parser executing on p == pe (EOF)"); #line 560 "HttpParser.cs" { sbyte _klen; short _trans; int _acts; int _nacts; short _keys; if (p == pe) { goto _test_eof; } if (cs == 0) { goto _out; } _resume: _acts = _http_parser_from_state_actions[cs]; _nacts = _http_parser_actions[_acts++]; while (_nacts-- > 0) { switch (_http_parser_actions[_acts++]) { case 30: #line 307 "HttpParser.cs.rl" { throw new Exception("Parser is dead; there shouldn't be more data. Client is bogus? fpc =" + p); } break; #line 583 "HttpParser.cs" default: break; } } _keys = _http_parser_key_offsets[cs]; _trans = (short)_http_parser_index_offsets[cs]; _klen = _http_parser_single_lengths[cs]; if (_klen > 0) { short _lower = _keys; short _mid; short _upper = (short)(_keys + _klen - 1); while (true) { if (_upper < _lower) { break; } _mid = (short)(_lower + ((_upper - _lower) >> 1)); if (data[p] < _http_parser_trans_keys[_mid]) { _upper = (short)(_mid - 1); } else if (data[p] > _http_parser_trans_keys[_mid]) { _lower = (short)(_mid + 1); } else { _trans += (short)(_mid - _keys); goto _match; } } _keys += (short)_klen; _trans += (short)_klen; } _klen = _http_parser_range_lengths[cs]; if (_klen > 0) { short _lower = _keys; short _mid; short _upper = (short)(_keys + (_klen << 1) - 2); while (true) { if (_upper < _lower) { break; } _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1)); if (data[p] < _http_parser_trans_keys[_mid]) { _upper = (short)(_mid - 2); } else if (data[p] > _http_parser_trans_keys[_mid + 1]) { _lower = (short)(_mid + 2); } else { _trans += (short)((_mid - _keys) >> 1); goto _match; } } _trans += (short)_klen; } _match: _trans = (short)_http_parser_indicies[_trans]; cs = _http_parser_trans_targs[_trans]; if (_http_parser_trans_actions[_trans] == 0) { goto _again; } _acts = _http_parser_trans_actions[_trans]; _nacts = _http_parser_actions[_acts++]; while (_nacts-- > 0) { switch (_http_parser_actions[_acts++]) { case 0: #line 38 "HttpParser.cs.rl" { sb.Append((char)data[p]); } break; case 1: #line 42 "HttpParser.cs.rl" { sb.Length = 0; } break; case 2: #line 46 "HttpParser.cs.rl" { sb2.Append((char)data[p]); } break; case 3: #line 50 "HttpParser.cs.rl" { if (sb2 == null) { sb2 = new StringBuilder(); } sb2.Length = 0; } break; case 4: #line 56 "HttpParser.cs.rl" { //Console.WriteLine("message_begin"); versionMajor = 0; versionMinor = 9; contentLength = -1; inContentLengthHeader = false; inConnectionHeader = false; inTransferEncodingHeader = false; inUpgradeHeader = false; gotConnectionClose = false; gotConnectionKeepAlive = false; gotTransferEncodingChunked = false; gotUpgradeValue = false; parser.OnMessageBegin(this); } break; case 5: #line 74 "HttpParser.cs.rl" { //Console.WriteLine("matched absolute_uri"); } break; case 6: #line 77 "HttpParser.cs.rl" { //Console.WriteLine("matched abs_path"); } break; case 7: #line 80 "HttpParser.cs.rl" { //Console.WriteLine("matched authority"); } break; case 8: #line 83 "HttpParser.cs.rl" { //Console.WriteLine("matched first space"); } break; case 9: #line 86 "HttpParser.cs.rl" { //Console.WriteLine("leave_first_space"); } break; case 11: #line 95 "HttpParser.cs.rl" { //Console.WriteLine("matched_leading_crlf"); } break; case 12: #line 105 "HttpParser.cs.rl" { parser.OnMethod(this, sb.ToString()); } break; case 13: #line 109 "HttpParser.cs.rl" { parser.OnRequestUri(this, sb.ToString()); } break; case 14: #line 114 "HttpParser.cs.rl" { parser.OnQueryString(this, sb2.ToString()); } break; case 15: #line 129 "HttpParser.cs.rl" { parser.OnFragment(this, sb2.ToString()); } break; case 16: #line 143 "HttpParser.cs.rl" { versionMajor = (char)data[p] - '0'; } break; case 17: #line 147 "HttpParser.cs.rl" { versionMinor = (char)data[p] - '0'; } break; case 18: #line 151 "HttpParser.cs.rl" { if (contentLength != -1) { throw new Exception("Already got Content-Length. Possible attack?"); } //Console.WriteLine("Saw content length"); contentLength = 0; inContentLengthHeader = true; } break; case 19: #line 158 "HttpParser.cs.rl" { //Console.WriteLine("header_connection"); inConnectionHeader = true; } break; case 20: #line 163 "HttpParser.cs.rl" { //Console.WriteLine("header_connection_close"); if (inConnectionHeader) { gotConnectionClose = true; } } break; case 21: #line 169 "HttpParser.cs.rl" { //Console.WriteLine("header_connection_keepalive"); if (inConnectionHeader) { gotConnectionKeepAlive = true; } } break; case 22: #line 175 "HttpParser.cs.rl" { //Console.WriteLine("Saw transfer encoding"); inTransferEncodingHeader = true; } break; case 23: #line 180 "HttpParser.cs.rl" { if (inTransferEncodingHeader) { gotTransferEncodingChunked = true; } } break; case 24: #line 185 "HttpParser.cs.rl" { inUpgradeHeader = true; } break; case 25: #line 189 "HttpParser.cs.rl" { parser.OnHeaderName(this, sb.ToString()); } break; case 26: #line 193 "HttpParser.cs.rl" { var str = sb.ToString(); //Console.WriteLine("on_header_value '" + str + "'"); //Console.WriteLine("inContentLengthHeader " + inContentLengthHeader); if (inContentLengthHeader) { contentLength = int.Parse(str); } inConnectionHeader = inTransferEncodingHeader = inContentLengthHeader = false; parser.OnHeaderValue(this, str); } break; case 27: #line 205 "HttpParser.cs.rl" { if (data[p] == 10) { //Console.WriteLine("leave_headers contentLength = " + contentLength); parser.OnHeadersEnd(this); // if chunked transfer, ignore content length and parse chunked (but we can't yet so bail) // if content length given but zero, read next request // if content length is given and non-zero, we should read that many bytes // if content length is not given // if should keep alive, assume next request is coming and read it // else read body until EOF if (contentLength == 0) { parser.OnMessageEnd(this); //fhold; { cs = 1; if (true) { goto _again; } } } else if (contentLength > 0) { //fhold; { cs = 129; if (true) { goto _again; } } } else { //Console.WriteLine("Request had no content length."); if (ShouldKeepAlive) { parser.OnMessageEnd(this); //Console.WriteLine("Should keep alive, will read next message."); //fhold; { cs = 1; if (true) { goto _again; } } } else { //Console.WriteLine("Not keeping alive, will read until eof. Will hold, but currently fpc = " + fpc); //fhold; { cs = 133; if (true) { goto _again; } } } } } } break; case 28: #line 250 "HttpParser.cs.rl" { var toRead = Math.Min(pe - p, contentLength); //Console.WriteLine("body_identity: reading " + toRead + " bytes from body."); if (toRead > 0) { parser.OnBody(this, new ArraySegment <byte>(data, p, toRead)); p += toRead - 1; contentLength -= toRead; //Console.WriteLine("content length is now " + contentLength); if (contentLength == 0) { parser.OnMessageEnd(this); if (ShouldKeepAlive) { //Console.WriteLine("Transitioning from identity body to next message."); //fhold; { cs = 1; if (true) { goto _again; } } } else { //fhold; { cs = 130; if (true) { goto _again; } } } } else { { p++; if (true) { goto _out; } } } } } break; case 29: #line 283 "HttpParser.cs.rl" { var toRead = pe - p; //Console.WriteLine("body_identity_eof: reading " + toRead + " bytes from body."); if (toRead > 0) { parser.OnBody(this, new ArraySegment <byte>(data, p, toRead)); p += toRead - 1; { p++; if (true) { goto _out; } } } else { parser.OnMessageEnd(this); if (ShouldKeepAlive) { cs = 1; if (true) { goto _again; } } else { //Console.WriteLine("body_identity_eof: going to dead"); p--; { cs = 130; if (true) { goto _again; } } } } } break; #line 947 "HttpParser.cs" default: break; } } _again: if (cs == 0) { goto _out; } if (++p != pe) { goto _resume; } _test_eof : {} if (p == eof) { int __acts = _http_parser_eof_actions[cs]; int __nacts = _http_parser_actions[__acts++]; while (__nacts-- > 0) { switch (_http_parser_actions[__acts++]) { case 10: #line 89 "HttpParser.cs.rl" { //Console.WriteLine("eof_leave_first_space"); } break; case 29: #line 283 "HttpParser.cs.rl" { var toRead = pe - p; //Console.WriteLine("body_identity_eof: reading " + toRead + " bytes from body."); if (toRead > 0) { parser.OnBody(this, new ArraySegment <byte>(data, p, toRead)); p += toRead - 1; { p++; if (true) { goto _out; } } } else { parser.OnMessageEnd(this); if (ShouldKeepAlive) { cs = 1; if (true) { goto _again; } } else { //Console.WriteLine("body_identity_eof: going to dead"); p--; { cs = 130; if (true) { goto _again; } } } } } break; #line 996 "HttpParser.cs" default: break; } } } _out : {} } #line 337 "HttpParser.cs.rl" var result = p - buf.Offset; if (result != buf.Count) { Console.WriteLine("error on character " + p); Console.WriteLine("('" + buf.Array[p] + "')"); Console.WriteLine("('" + (char)buf.Array[p] + "')"); } return(p - buf.Offset); }