1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "source/common/http/http1/parser.h"
6
#include "source/common/runtime/runtime_features.h"
7

            
8
#include "absl/base/attributes.h"
9
#include "quiche/balsa/balsa_enums.h"
10
#include "quiche/balsa/balsa_frame.h"
11
#include "quiche/balsa/balsa_headers.h"
12
#include "quiche/balsa/balsa_visitor_interface.h"
13

            
14
namespace Envoy {
15
namespace Http {
16
namespace Http1 {
17

            
18
// This class wraps BalsaFrame and BalsaHeaders into a Parser implementation
19
// to be used by ConnectionImpl.
20
class BalsaParser : public Parser, public quiche::BalsaVisitorInterface {
21
public:
22
  BalsaParser(MessageType type, ParserCallbacks* connection, size_t max_header_length,
23
              bool enable_trailers, bool allow_custom_methods);
24
69461
  ~BalsaParser() override = default;
25

            
26
  // Http1::Parser implementation
27
  size_t execute(const char* slice, int len) override;
28
  void resume() override;
29
  CallbackResult pause() override;
30
  ParserStatus getStatus() const override;
31
  Http::Code statusCode() const override;
32
  bool isHttp11() const override;
33
  absl::optional<uint64_t> contentLength() const override;
34
  bool isChunked() const override;
35
  absl::string_view methodName() const override;
36
  absl::string_view errorMessage() const override;
37
  int hasTransferEncoding() const override;
38

            
39
private:
40
  // quiche::BalsaVisitorInterface implementation
41
  // TODO(bnc): Encapsulate in a private object.
42
  void OnRawBodyInput(absl::string_view input) override;
43
  void OnBodyChunkInput(absl::string_view input) override;
44
  void OnHeaderInput(absl::string_view input) override;
45
  void OnTrailerInput(absl::string_view input) override;
46
  void OnTrailers(std::unique_ptr<quiche::BalsaHeaders> trailers) override;
47
  void ProcessHeaders(const quiche::BalsaHeaders& headers) override;
48
  void OnRequestFirstLineInput(absl::string_view line_input, absl::string_view method_input,
49
                               absl::string_view request_uri,
50
                               absl::string_view version_input) override;
51
  void OnResponseFirstLineInput(absl::string_view line_input, absl::string_view version_input,
52
                                absl::string_view status_input,
53
                                absl::string_view reason_input) override;
54
  void OnChunkLength(size_t chunk_length) override;
55
  void OnChunkExtensionInput(absl::string_view input) override;
56
  void OnInterimHeaders(std::unique_ptr<quiche::BalsaHeaders> headers) override;
57
  void HeaderDone() override;
58
  void ContinueHeaderDone() override;
59
  void MessageDone() override;
60
  void HandleError(quiche::BalsaFrameEnums::ErrorCode error_code) override;
61
  void HandleWarning(quiche::BalsaFrameEnums::ErrorCode error_code) override;
62

            
63
  // Shared implementation for ProcessHeaders() and OnTrailers().
64
  void validateAndProcessHeadersOrTrailersImpl(const quiche::BalsaHeaders& headers, bool trailers);
65

            
66
  // Return ParserStatus::Error if `result` is CallbackResult::Error.
67
  // Return current value of `status_` otherwise.
68
  // Typical use would be `status_ = convertResult(result);`
69
  ABSL_MUST_USE_RESULT ParserStatus convertResult(CallbackResult result) const;
70

            
71
  quiche::BalsaFrame framer_;
72
  quiche::BalsaHeaders headers_;
73

            
74
  const MessageType message_type_ = MessageType::Request;
75
  ParserCallbacks* connection_ = nullptr;
76
  const bool enable_trailers_ = false;
77
  const bool allow_custom_methods_ = false;
78
  bool first_byte_processed_ = false;
79
  bool headers_done_ = false;
80
  // True until the first byte of the second message arrives.
81
  bool first_message_ = true;
82
  ParserStatus status_ = ParserStatus::Ok;
83
  // An error message, often seemingly arbitrary to match http-parser behavior.
84
  absl::string_view error_message_;
85
};
86

            
87
} // namespace Http1
88
} // namespace Http
89
} // namespace Envoy