예제 #1
0
 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;
         }
     });
 }
예제 #2
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);
        }