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
110633
  void decodeHeaders(ResponseHeaderMapPtr&& headers, bool end_stream) override {
26
110633
    if (end_stream) {
27
69785
      onPreDecodeComplete();
28
69785
    }
29
110633
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
30
110632
      inner->decodeHeaders(std::move(headers), end_stream);
31
110633
    } else {
32
1
      onInnerDecoderDead();
33
1
    }
34
110633
    if (end_stream) {
35
69785
      onDecodeComplete();
36
69785
    }
37
110633
  }
38

            
39
706442
  void decodeData(Buffer::Instance& data, bool end_stream) override {
40
706442
    if (end_stream) {
41
35456
      onPreDecodeComplete();
42
35456
    }
43
706445
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
44
706441
      inner->decodeData(data, end_stream);
45
704072
    } else {
46
4
      onInnerDecoderDead();
47
4
    }
48
706442
    if (end_stream) {
49
35456
      onDecodeComplete();
50
35456
    }
51
706442
  }
52

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

            
63
1718
  void decodeMetadata(MetadataMapPtr&& metadata_map) override {
64
1718
    if (Http::ResponseDecoder* inner = getInnerDecoder()) {
65
1717
      inner->decodeMetadata(std::move(metadata_map));
66
1718
    } else {
67
1
      onInnerDecoderDead();
68
1
    }
69
1718
  }
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
76949
  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
46910
      : 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
821129
  Http::ResponseDecoder* getInnerDecoder() const {
101
821129
    if (inner_handle_ == nullptr) {
102
198475
      return inner_;
103
198475
    }
104
622656
    if (inner_handle_) {
105
622656
      if (OptRef<ResponseDecoder> inner = inner_handle_->get(); inner.has_value()) {
106
622650
        return &inner.value().get();
107
622650
      }
108
622656
    }
109
6
    return nullptr;
110
622654
  }
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
123218
  Status encodeHeaders(const RequestHeaderMap& headers, bool end_stream) override {
128
123218
    ASSERT(inner_encoder_);
129
123218
    RETURN_IF_ERROR(inner_encoder_->encodeHeaders(headers, end_stream));
130
123164
    if (end_stream) {
131
91454
      onEncodeComplete();
132
91454
    }
133
123164
    return okStatus();
134
123218
  }
135

            
136
318375
  void encodeData(Buffer::Instance& data, bool end_stream) override {
137
318375
    ASSERT(inner_encoder_);
138
318375
    inner_encoder_->encodeData(data, end_stream);
139
318375
    if (end_stream) {
140
17481
      onEncodeComplete();
141
17481
    }
142
318375
  }
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
2248
  void encodeMetadata(const MetadataMapVector& metadata_map_vector) override {
156
2248
    ASSERT(inner_encoder_);
157
2248
    inner_encoder_->encodeMetadata(metadata_map_vector);
158
2248
  }
159

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

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

            
170
protected:
171
123860
  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