1
#pragma once
2

            
3
#include "envoy/http/codec.h"
4

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

            
8
namespace Envoy {
9
namespace Http {
10

            
11
/**
12
 * Wrapper for ResponseDecoder that just forwards to an "inner" decoder.
13
 */
14
class ResponseDecoderWrapper : public ResponseDecoderImplBase {
15
public:
16
  // ResponseDecoder
17
444
  void decode1xxHeaders(ResponseHeaderMapPtr&& headers) override {
18
444
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
19
443
      inner->decode1xxHeaders(std::move(headers));
20
444
    } else {
21
1
      onInnerDecoderDead();
22
1
    }
23
444
  }
24

            
25
110343
  void decodeHeaders(ResponseHeaderMapPtr&& headers, bool end_stream) override {
26
110343
    if (end_stream) {
27
69830
      onPreDecodeComplete();
28
69830
    }
29
110343
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
30
110342
      inner->decodeHeaders(std::move(headers), end_stream);
31
110343
    } else {
32
1
      onInnerDecoderDead();
33
1
    }
34
110343
    if (end_stream) {
35
69830
      onDecodeComplete();
36
69830
    }
37
110343
  }
38

            
39
705634
  void decodeData(Buffer::Instance& data, bool end_stream) override {
40
705634
    if (end_stream) {
41
35168
      onPreDecodeComplete();
42
35168
    }
43
705635
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
44
705632
      inner->decodeData(data, end_stream);
45
705069
    } else {
46
3
      onInnerDecoderDead();
47
3
    }
48
705634
    if (end_stream) {
49
35168
      onDecodeComplete();
50
35168
    }
51
705634
  }
52

            
53
1887
  void decodeTrailers(ResponseTrailerMapPtr&& trailers) override {
54
1887
    onPreDecodeComplete();
55
1887
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
56
1886
      inner->decodeTrailers(std::move(trailers));
57
1887
    } else {
58
1
      onInnerDecoderDead();
59
1
    }
60
1887
    onDecodeComplete();
61
1887
  }
62

            
63
1723
  void decodeMetadata(MetadataMapPtr&& metadata_map) override {
64
1723
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
65
1722
      inner->decodeMetadata(std::move(metadata_map));
66
1723
    } else {
67
1
      onInnerDecoderDead();
68
1
    }
69
1723
  }
70

            
71
2
  void dumpState(std::ostream& os, int indent_level) const override {
72
2
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
73
1
      inner->dumpState(os, indent_level);
74
1
    } else {
75
1
      onInnerDecoderDead();
76
1
    }
77
2
  }
78

            
79
protected:
80
76826
  ResponseDecoderWrapper(ResponseDecoder& inner) : inner_(&inner) {}
81

            
82
  /**
83
   * @param inner_handle refers a response decoder which may have already died at
84
   * this point. Following access to the decoder will check its liveliness.
85
   */
86
  ResponseDecoderWrapper(ResponseDecoderHandlePtr inner_handle)
87
46727
      : inner_handle_(std::move(inner_handle)) {}
88

            
89
  /**
90
   * Consumers of the wrapper generally want to know when a decode is complete. This is called
91
   * at that time and is implemented by derived classes.
92
   */
93
  virtual void onPreDecodeComplete() PURE;
94
  virtual void onDecodeComplete() PURE;
95

            
96
  ResponseDecoderHandlePtr inner_handle_;
97
  Http::ResponseDecoder* inner_ = nullptr;
98

            
99
private:
100
820031
  Http::ResponseDecoder* getInnerDecoder() const {
101
820031
    if (inner_handle_ == nullptr) {
102
197911
      return inner_;
103
197911
    }
104
622121
    if (inner_handle_) {
105
622121
      if (OptRef<ResponseDecoder> inner = inner_handle_->get(); inner.has_value()) {
106
622115
        return &inner.value().get();
107
622115
      }
108
622121
    }
109
6
    return nullptr;
110
622120
  }
111

            
112
6
  void onInnerDecoderDead() const {
113
6
    const std::string error_msg = "Wrapped decoder use after free detected.";
114
6
    IS_ENVOY_BUG(error_msg);
115
6
    RELEASE_ASSERT(!Runtime::runtimeFeatureEnabled(
116
6
                       "envoy.reloadable_features.abort_when_accessing_dead_decoder"),
117
6
                   error_msg);
118
6
  }
119
};
120

            
121
/**
122
 * Wrapper for RequestEncoder that just forwards to an "inner" encoder.
123
 */
124
class RequestEncoderWrapper : public RequestEncoder {
125
public:
126
  // RequestEncoder
127
122908
  Status encodeHeaders(const RequestHeaderMap& headers, bool end_stream) override {
128
122908
    ASSERT(inner_encoder_);
129
122908
    RETURN_IF_ERROR(inner_encoder_->encodeHeaders(headers, end_stream));
130
122855
    if (end_stream) {
131
91134
      onEncodeComplete();
132
91134
    }
133
122855
    return okStatus();
134
122908
  }
135

            
136
319174
  void encodeData(Buffer::Instance& data, bool end_stream) override {
137
319174
    ASSERT(inner_encoder_);
138
319174
    inner_encoder_->encodeData(data, end_stream);
139
319174
    if (end_stream) {
140
17548
      onEncodeComplete();
141
17548
    }
142
319174
  }
143

            
144
937
  void encodeTrailers(const RequestTrailerMap& trailers) override {
145
937
    ASSERT(inner_encoder_);
146
937
    inner_encoder_->encodeTrailers(trailers);
147
937
    onEncodeComplete();
148
937
  }
149

            
150
822
  void enableTcpTunneling() override {
151
822
    ASSERT(inner_encoder_);
152
822
    inner_encoder_->enableTcpTunneling();
153
822
  }
154

            
155
2237
  void encodeMetadata(const MetadataMapVector& metadata_map_vector) override {
156
2237
    ASSERT(inner_encoder_);
157
2237
    inner_encoder_->encodeMetadata(metadata_map_vector);
158
2237
  }
159

            
160
437565
  Stream& getStream() override {
161
437565
    ASSERT(inner_encoder_);
162
437565
    return inner_encoder_->getStream();
163
437565
  }
164

            
165
1
  Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override {
166
1
    ASSERT(inner_encoder_);
167
1
    return inner_encoder_->http1StreamEncoderOptions();
168
1
  }
169

            
170
protected:
171
123554
  RequestEncoderWrapper(RequestEncoder* inner) : inner_encoder_(inner) {}
172

            
173
  /**
174
   * Consumers of the wrapper generally want to know when an encode is complete. This is called at
175
   * that time and is implemented by derived classes.
176
   */
177
  virtual void onEncodeComplete() PURE;
178

            
179
  RequestEncoder* inner_encoder_;
180
};
181

            
182
} // namespace Http
183
} // namespace Envoy