Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/http/http1/codec_impl.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <array>
4
#include <cstdint>
5
#include <list>
6
#include <memory>
7
#include <string>
8
9
#include "envoy/common/optref.h"
10
#include "envoy/common/scope_tracker.h"
11
#include "envoy/config/core/v3/protocol.pb.h"
12
#include "envoy/http/codec.h"
13
#include "envoy/network/connection.h"
14
#include "envoy/server/overload/overload_manager.h"
15
16
#include "source/common/buffer/watermark_buffer.h"
17
#include "source/common/common/assert.h"
18
#include "source/common/common/statusor.h"
19
#include "source/common/http/codec_helper.h"
20
#include "source/common/http/codes.h"
21
#include "source/common/http/header_map_impl.h"
22
#include "source/common/http/http1/codec_stats.h"
23
#include "source/common/http/http1/header_formatter.h"
24
#include "source/common/http/http1/parser.h"
25
#include "source/common/http/status.h"
26
27
namespace Envoy {
28
namespace Http {
29
namespace Http1 {
30
31
// The default limit of 80 KiB is the vanilla http_parser behaviour.
32
inline constexpr uint32_t MAX_RESPONSE_HEADERS_KB = 80;
33
34
class ConnectionImpl;
35
36
/**
37
 * Base class for HTTP/1.1 request and response encoders.
38
 */
39
class StreamEncoderImpl : public virtual StreamEncoder,
40
                          public Stream,
41
                          public Logger::Loggable<Logger::Id::http>,
42
                          public StreamCallbackHelper,
43
                          public Http1StreamEncoderOptions {
44
public:
45
39.5k
  ~StreamEncoderImpl() override {
46
    // When the stream goes away, undo any read blocks to resume reading.
47
43.8k
    while (read_disable_calls_ != 0) {
48
4.30k
      StreamEncoderImpl::readDisable(false);
49
4.30k
    }
50
39.5k
  }
51
  // Http::StreamEncoder
52
  void encodeData(Buffer::Instance& data, bool end_stream) override;
53
  void encodeMetadata(const MetadataMapVector&) override;
54
823k
  Stream& getStream() override { return *this; }
55
0
  Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() override { return *this; }
56
57
  // Http::Http1StreamEncoderOptions
58
274
  void disableChunkEncoding() override { disable_chunk_encoding_ = true; }
59
60
  // Http::Stream
61
25.7k
  void addCallbacks(StreamCallbacks& callbacks) override { addCallbacksHelper(callbacks); }
62
6.82k
  void removeCallbacks(StreamCallbacks& callbacks) override { removeCallbacksHelper(callbacks); }
63
  CodecEventCallbacks* registerCodecEventCallbacks(CodecEventCallbacks* codec_callbacks) override;
64
  // After this is called, for the HTTP/1 codec, the connection should be closed, i.e. no further
65
  // progress may be made with the codec.
66
  void resetStream(StreamResetReason reason) override;
67
  void readDisable(bool disable) override;
68
  uint32_t bufferLimit() const override;
69
1.41k
  absl::string_view responseDetails() override { return details_; }
70
  const Network::ConnectionInfoProvider& connectionInfoProvider() override;
71
3.87k
  void setFlushTimeout(std::chrono::milliseconds) override {
72
    // HTTP/1 has one stream per connection, thus any data encoded is immediately written to the
73
    // connection, invoking any watermarks as necessary. There is no internal buffering that would
74
    // require a flush timeout not already covered by other timeouts.
75
3.87k
  }
76
77
3.87k
  Buffer::BufferMemoryAccountSharedPtr account() const override { return buffer_memory_account_; }
78
79
3.91k
  void setAccount(Buffer::BufferMemoryAccountSharedPtr account) override {
80
    // TODO(kbaichoo): implement account tracking for H1. Particularly, binding
81
    // the account to the buffers used. The current wiring is minimal, and used
82
    // to ensure the memory_account gets notified that the downstream request is
83
    // closing.
84
3.91k
    buffer_memory_account_ = account;
85
3.91k
  }
86
87
16.8k
  void setIsResponseToHeadRequest(bool value) { is_response_to_head_request_ = value; }
88
16.8k
  void setIsResponseToConnectRequest(bool value) { is_response_to_connect_request_ = value; }
89
14.3k
  void setDetails(absl::string_view details) { details_ = details; }
90
91
758k
  const StreamInfo::BytesMeterSharedPtr& bytesMeter() override { return bytes_meter_; }
92
93
protected:
94
  StreamEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter);
95
  void encodeHeadersBase(const RequestOrResponseHeaderMap& headers, absl::optional<uint64_t> status,
96
                         bool end_stream, bool bodiless_request);
97
  void encodeTrailersBase(const HeaderMap& headers);
98
99
  Buffer::BufferMemoryAccountSharedPtr buffer_memory_account_;
100
  ConnectionImpl& connection_;
101
  uint32_t read_disable_calls_{};
102
  bool disable_chunk_encoding_ : 1;
103
  bool chunk_encoding_ : 1;
104
  bool connect_request_ : 1;
105
  bool is_tcp_tunneling_ : 1;
106
  bool is_response_to_head_request_ : 1;
107
  bool is_response_to_connect_request_ : 1;
108
109
private:
110
  /**
111
   * Called to encode an individual header.
112
   * @param key supplies the header to encode as a string_view.
113
   * @param value supplies the value to encode as a string_view.
114
   */
115
  void encodeHeader(absl::string_view key, absl::string_view value);
116
117
  /**
118
   * Called to finalize a stream encode.
119
   */
120
  void endEncode();
121
122
  /**
123
   * Encapsulates notification to various objects that the encode completed.
124
   */
125
  void notifyEncodeComplete();
126
127
  void encodeFormattedHeader(absl::string_view key, absl::string_view value,
128
                             HeaderKeyFormatterOptConstRef formatter);
129
130
  void flushOutput(bool end_encode = false);
131
132
  absl::string_view details_;
133
  StreamInfo::BytesMeterSharedPtr bytes_meter_;
134
  CodecEventCallbacks* codec_callbacks_{nullptr};
135
};
136
137
/**
138
 * HTTP/1.1 response encoder.
139
 */
140
class ResponseEncoderImpl : public StreamEncoderImpl, public ResponseEncoder {
141
public:
142
  ResponseEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter,
143
                      bool stream_error_on_invalid_http_message)
144
      : StreamEncoderImpl(connection, std::move(bytes_meter)),
145
27.9k
        stream_error_on_invalid_http_message_(stream_error_on_invalid_http_message) {}
Unexecuted instantiation: Envoy::Http::Http1::ResponseEncoderImpl::ResponseEncoderImpl(Envoy::Http::Http1::ConnectionImpl&, std::__1::shared_ptr<Envoy::StreamInfo::BytesMeter>&&, bool)
Envoy::Http::Http1::ResponseEncoderImpl::ResponseEncoderImpl(Envoy::Http::Http1::ConnectionImpl&, std::__1::shared_ptr<Envoy::StreamInfo::BytesMeter>&&, bool)
Line
Count
Source
145
27.9k
        stream_error_on_invalid_http_message_(stream_error_on_invalid_http_message) {}
146
147
27.9k
  ~ResponseEncoderImpl() override {
148
    // Only the downstream stream should clear the downstream of the
149
    // memory account.
150
    //
151
    // There are cases where a corresponding upstream stream dtor might
152
    // be called, but the downstream stream isn't going to terminate soon
153
    // such as StreamDecoderFilterCallbacks::recreateStream().
154
27.9k
    if (buffer_memory_account_) {
155
0
      buffer_memory_account_->clearDownstream();
156
0
    }
157
27.9k
  }
158
159
13.8k
  bool startedResponse() { return started_response_; }
160
161
  // Http::ResponseEncoder
162
  void encode1xxHeaders(const ResponseHeaderMap& headers) override;
163
  void encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) override;
164
28
  void encodeTrailers(const ResponseTrailerMap& trailers) override { encodeTrailersBase(trailers); }
165
166
664
  bool streamErrorOnInvalidHttpMessage() const override {
167
664
    return stream_error_on_invalid_http_message_;
168
664
  }
169
  void setDeferredLoggingHeadersAndTrailers(Http::RequestHeaderMapConstSharedPtr,
170
                                            Http::ResponseHeaderMapConstSharedPtr,
171
                                            Http::ResponseTrailerMapConstSharedPtr,
172
0
                                            StreamInfo::StreamInfo&) override {}
173
174
  // For H/1, ResponseEncoder doesn't hold a pointer to RequestDecoder.
175
  // TODO(paulsohn): Enable H/1 codec to get a pointer to the new
176
  // request decoder on recreateStream, here or elsewhere.
177
0
  void setRequestDecoder(Http::RequestDecoder& /*decoder*/) override {}
178
179
  // Http1::StreamEncoderImpl
180
  void resetStream(StreamResetReason reason) override;
181
182
private:
183
  bool started_response_{};
184
  const bool stream_error_on_invalid_http_message_;
185
};
186
187
/**
188
 * HTTP/1.1 request encoder.
189
 */
190
class RequestEncoderImpl : public StreamEncoderImpl, public RequestEncoder {
191
public:
192
  RequestEncoderImpl(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter)
193
11.6k
      : StreamEncoderImpl(connection, std::move(bytes_meter)) {}
Unexecuted instantiation: Envoy::Http::Http1::RequestEncoderImpl::RequestEncoderImpl(Envoy::Http::Http1::ConnectionImpl&, std::__1::shared_ptr<Envoy::StreamInfo::BytesMeter>&&)
Envoy::Http::Http1::RequestEncoderImpl::RequestEncoderImpl(Envoy::Http::Http1::ConnectionImpl&, std::__1::shared_ptr<Envoy::StreamInfo::BytesMeter>&&)
Line
Count
Source
193
11.6k
      : StreamEncoderImpl(connection, std::move(bytes_meter)) {}
194
49
  bool upgradeRequest() const { return upgrade_request_; }
195
17.0k
  bool headRequest() const { return head_request_; }
196
5.43k
  bool connectRequest() const { return connect_request_; }
197
198
  // Http::RequestEncoder
199
  Status encodeHeaders(const RequestHeaderMap& headers, bool end_stream) override;
200
2.43k
  void encodeTrailers(const RequestTrailerMap& trailers) override { encodeTrailersBase(trailers); }
201
0
  void enableTcpTunneling() override { is_tcp_tunneling_ = true; }
202
203
private:
204
  bool upgrade_request_{};
205
  bool head_request_{};
206
};
207
208
/**
209
 * Base class for HTTP/1.1 client and server connections.
210
 * Handles the callbacks of http_parser with its own base routine and then
211
 * virtual dispatches to its subclasses.
212
 */
213
class ConnectionImpl : public virtual Connection,
214
                       protected Logger::Loggable<Logger::Id::http>,
215
                       public ParserCallbacks,
216
                       public ScopeTrackedObject {
217
public:
218
  /**
219
   * @return Network::Connection& the backing network connection.
220
   */
221
77.1k
  Network::Connection& connection() { return connection_; }
222
0
  const Network::Connection& connection() const { return connection_; }
223
224
  /**
225
   * Called when the active encoder has completed encoding the outbound half of the stream.
226
   */
227
  virtual void onEncodeComplete() PURE;
228
229
  virtual StreamInfo::BytesMeter& getBytesMeter() PURE;
230
231
  /**
232
   * Called when resetStream() has been called on an active stream. In HTTP/1.1 the only
233
   * valid operation after this point is for the connection to get blown away, but we will not
234
   * fire any more callbacks in case some stack has to unwind.
235
   */
236
  void onResetStreamBase(StreamResetReason reason);
237
238
  /**
239
   * Flush all pending output from encoding.
240
   */
241
  uint64_t flushOutput(bool end_encode = false);
242
243
171k
  Buffer::Instance& buffer() { return *output_buffer_; }
244
245
8.63k
  void readDisable(bool disable) {
246
8.63k
    if (connection_.state() == Network::Connection::State::Open) {
247
8.61k
      connection_.readDisable(disable);
248
8.61k
    }
249
8.63k
  }
250
3.87k
  uint32_t bufferLimit() { return connection_.bufferLimit(); }
251
0
  virtual bool supportsHttp10() { return false; }
252
  bool maybeDirectDispatch(Buffer::Instance& data);
253
6.24k
  virtual void maybeAddSentinelBufferFragment(Buffer::Instance&) {}
254
182
  CodecStats& stats() { return stats_; }
255
22.0k
  bool enableTrailers() const { return codec_settings_.enable_trailers_; }
256
11.4k
  virtual bool sendFullyQualifiedUrl() const { return codec_settings_.send_fully_qualified_url_; }
257
26.1k
  HeaderKeyFormatterOptConstRef formatter() const {
258
26.1k
    return makeOptRefFromPtr(encode_only_header_key_formatter_.get());
259
26.1k
  }
260
261
  // Http::Connection
262
  Http::Status dispatch(Buffer::Instance& data) override;
263
0
  void goAway() override {} // Called during connection manager drain flow
264
148k
  Protocol protocol() override { return protocol_; }
265
0
  void shutdownNotice() override {} // Called during connection manager drain flow
266
893
  bool wantsToWrite() override { return false; }
267
0
  void onUnderlyingConnectionAboveWriteBufferHighWatermark() override { onAboveHighWatermark(); }
268
0
  void onUnderlyingConnectionBelowWriteBufferLowWatermark() override { onBelowLowWatermark(); }
269
270
  // Codec errors found in callbacks are overridden within the http_parser library. This holds those
271
  // errors to propagate them through to dispatch() where we can handle the error.
272
  Envoy::Http::Status codec_status_;
273
274
  // ScopeTrackedObject
275
  void dumpState(std::ostream& os, int indent_level) const override;
276
277
protected:
278
  ConnectionImpl(Network::Connection& connection, CodecStats& stats, const Http1Settings& settings,
279
                 MessageType type, uint32_t max_headers_kb, const uint32_t max_headers_count);
280
281
28.4k
  bool resetStreamCalled() { return reset_stream_called_; }
282
283
  // This must be protected because it is called through ServerConnectionImpl::sendProtocolError.
284
  Status onMessageBeginImpl();
285
286
  /**
287
   * Get memory used to represent HTTP headers or trailers currently being parsed.
288
   * Computed by adding the partial header field and value that is currently being parsed and the
289
   * estimated header size for previous header lines provided by HeaderMap::byteSize().
290
   */
291
  virtual uint32_t getHeadersSize();
292
293
  /**
294
   * Called from onUrl, onHeaderFields and onHeaderValue to verify that the headers do not exceed
295
   * the configured max header size limit.
296
   * @return A codecProtocolError status if headers exceed the size limit.
297
   */
298
  Status checkMaxHeadersSize();
299
300
  Network::Connection& connection_;
301
  CodecStats& stats_;
302
  const Http1Settings codec_settings_;
303
  std::unique_ptr<Parser> parser_;
304
  Buffer::Instance* current_dispatching_buffer_{};
305
  Buffer::Instance* output_buffer_ = nullptr; // Not owned
306
  Http::Code error_code_{Http::Code::BadRequest};
307
  const HeaderKeyFormatterConstPtr encode_only_header_key_formatter_;
308
  HeaderString current_header_field_;
309
  HeaderString current_header_value_;
310
  bool processing_trailers_ : 1;
311
  bool handling_upgrade_ : 1;
312
  bool reset_stream_called_ : 1;
313
  // Deferred end stream headers indicate that we are not going to raise headers until the full
314
  // HTTP/1 message has been flushed from the parser. This allows raising an HTTP/2 style headers
315
  // block with end stream set to true with no further protocol data remaining.
316
  bool deferred_end_stream_headers_ : 1;
317
  bool dispatching_ : 1;
318
  bool dispatching_slice_already_drained_ : 1;
319
  StreamInfo::BytesMeterSharedPtr bytes_meter_before_stream_;
320
  const uint32_t max_headers_kb_;
321
  const uint32_t max_headers_count_;
322
323
private:
324
  enum class HeaderParsingState { Field, Value, Done };
325
0
  friend std::ostream& operator<<(std::ostream& os, HeaderParsingState parsing_state) {
326
0
    switch (parsing_state) {
327
0
    case ConnectionImpl::HeaderParsingState::Field:
328
0
      return os << "Field";
329
0
    case ConnectionImpl::HeaderParsingState::Value:
330
0
      return os << "Value";
331
0
    case ConnectionImpl::HeaderParsingState::Done:
332
0
      return os << "Done";
333
0
    }
334
0
    return os;
335
0
  }
336
337
  virtual HeaderMap& headersOrTrailers() PURE;
338
  virtual RequestOrResponseHeaderMap& requestOrResponseHeaders() PURE;
339
  virtual void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) PURE;
340
  virtual void allocTrailers() PURE;
341
342
  /**
343
   * Called for each header in order to complete an in progress header decode.
344
   * @return A status representing success.
345
   */
346
  Status completeCurrentHeader();
347
348
  /**
349
   * Check if header name contains underscore character.
350
   * Underscore character is allowed in header names by the RFC-7230 and this check is implemented
351
   * as a security measure due to systems that treat '_' and '-' as interchangeable.
352
   * The ServerConnectionImpl may drop header or reject request based on the
353
   * `common_http_protocol_options.headers_with_underscores_action` configuration option in the
354
   * HttpConnectionManager.
355
   */
356
0
  virtual bool shouldDropHeaderWithUnderscoresInNames(absl::string_view /* header_name */) const {
357
0
    return false;
358
0
  }
359
360
  /**
361
   * Dispatch a memory span.
362
   * @param slice supplies the start address.
363
   * @len supplies the length of the span.
364
   */
365
  Envoy::StatusOr<size_t> dispatchSlice(const char* slice, size_t len);
366
367
  void onDispatch(const Buffer::Instance& data);
368
369
  // ParserCallbacks.
370
  CallbackResult onMessageBegin() override;
371
  CallbackResult onUrl(const char* data, size_t length) override;
372
  CallbackResult onStatus(const char* data, size_t length) override;
373
  CallbackResult onHeaderField(const char* data, size_t length) override;
374
  CallbackResult onHeaderValue(const char* data, size_t length) override;
375
  CallbackResult onHeadersComplete() override;
376
  void bufferBody(const char* data, size_t length) override;
377
  CallbackResult onMessageComplete() override;
378
  void onChunkHeader(bool is_final_chunk) override;
379
380
  // Internal implementations of ParserCallbacks methods,
381
  // and virtual methods for connection-specific implementations.
382
  virtual Status onMessageBeginBase() PURE;
383
  virtual Status onUrlBase(const char* data, size_t length) PURE;
384
  virtual Status onStatusBase(const char* data, size_t length) PURE;
385
  Status onHeaderFieldImpl(const char* data, size_t length);
386
  Status onHeaderValueImpl(const char* data, size_t length);
387
  StatusOr<CallbackResult> onHeadersCompleteImpl();
388
  virtual StatusOr<CallbackResult> onHeadersCompleteBase() PURE;
389
  StatusOr<CallbackResult> onMessageCompleteImpl();
390
  virtual CallbackResult onMessageCompleteBase() PURE;
391
392
  // These helpers wrap *Impl() calls in the overrides of non-void
393
  // ParserCallbacks methods.
394
  CallbackResult setAndCheckCallbackStatus(Status&& status);
395
  CallbackResult setAndCheckCallbackStatusOr(StatusOr<CallbackResult>&& statusor);
396
397
  /**
398
   * Push the accumulated body through the filter pipeline.
399
   */
400
  void dispatchBufferedBody();
401
402
  /**
403
   * Called to see if upgrade transition is allowed.
404
   */
405
  virtual bool upgradeAllowed() const PURE;
406
407
  /**
408
   * Called with body data is available for processing when either:
409
   * - There is an accumulated partial body after the parser is done processing bytes read from the
410
   * socket
411
   * - The parser encounters the last byte of the body
412
   * - The codec does a direct dispatch from the read buffer
413
   * For performance reasons there is at most one call to onBody per call to HTTP/1
414
   * ConnectionImpl::dispatch call.
415
   * @param data supplies the body data
416
   */
417
  virtual void onBody(Buffer::Instance& data) PURE;
418
419
  /**
420
   * @see onResetStreamBase().
421
   */
422
  virtual void onResetStream(StreamResetReason reason) PURE;
423
424
  /**
425
   * Send a protocol error response to remote.
426
   */
427
  virtual Status sendProtocolError(absl::string_view details) PURE;
428
429
  /**
430
   * Called when output_buffer_ or the underlying connection go from below a low watermark to over
431
   * a high watermark.
432
   */
433
  virtual void onAboveHighWatermark() PURE;
434
435
  /**
436
   * Called when output_buffer_ or the underlying connection  go from above a high watermark to
437
   * below a low watermark.
438
   */
439
  virtual void onBelowLowWatermark() PURE;
440
441
  /**
442
   * Check if header name contains underscore character.
443
   * The ServerConnectionImpl may drop header or reject request based on configuration.
444
   * @return A status representing whether the request is rejected.
445
   */
446
36.4k
  virtual Status checkHeaderNameForUnderscores() { return okStatus(); }
447
448
  /**
449
   * Additional state to dump on crash.
450
   */
451
  virtual void dumpAdditionalState(std::ostream& os, int indent_level) const PURE;
452
453
  HeaderParsingState header_parsing_state_{HeaderParsingState::Field};
454
  // Used to accumulate the HTTP message body during the current dispatch call. The accumulated body
455
  // is pushed through the filter pipeline either at the end of the current dispatch call, or when
456
  // the last byte of the body is processed (whichever happens first).
457
  Buffer::OwnedImpl buffered_body_;
458
  Protocol protocol_{Protocol::Http11};
459
};
460
461
/**
462
 * Implementation of Http::ServerConnection for HTTP/1.1.
463
 */
464
class ServerConnectionImpl : public ServerConnection, public ConnectionImpl {
465
public:
466
  ServerConnectionImpl(Network::Connection& connection, CodecStats& stats,
467
                       ServerConnectionCallbacks& callbacks, const Http1Settings& settings,
468
                       uint32_t max_request_headers_kb, const uint32_t max_request_headers_count,
469
                       envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
470
                           headers_with_underscores_action,
471
                       Server::OverloadManager& overload_manager);
472
342
  bool supportsHttp10() override { return codec_settings_.accept_http_10_; }
473
474
protected:
475
  /**
476
   * An active HTTP/1.1 request.
477
   */
478
  struct ActiveRequest : public Event::DeferredDeletable {
479
    ActiveRequest(ServerConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter)
480
        : response_encoder_(connection, std::move(bytes_meter),
481
27.9k
                            connection.codec_settings_.stream_error_on_invalid_http_message_) {}
482
27.9k
    ~ActiveRequest() override = default;
483
484
    void dumpState(std::ostream& os, int indent_level) const;
485
    HeaderString request_url_;
486
    RequestDecoder* request_decoder_{};
487
    ResponseEncoderImpl response_encoder_;
488
    bool remote_complete_{};
489
  };
490
0
  ActiveRequest* activeRequest() { return active_request_.get(); }
491
  // ConnectionImpl
492
  CallbackResult onMessageCompleteBase() override;
493
  // Add the size of the request_url to the reported header size when processing request headers.
494
  uint32_t getHeadersSize() override;
495
496
private:
497
  /**
498
   * Manipulate the request's first line, parsing the url and converting to a relative path if
499
   * necessary. Compute Host / :authority headers based on 7230#5.7 and 7230#6
500
   *
501
   * @param is_connect true if the request has the CONNECT method
502
   * @param headers the request's headers
503
   * @return Status representing success or failure. This will fail if there is an invalid url in
504
   * the request line.
505
   */
506
  Status handlePath(RequestHeaderMap& headers, absl::string_view method);
507
508
  // ParserCallbacks.
509
  Status onUrlBase(const char* data, size_t length) override;
510
0
  Status onStatusBase(const char*, size_t) override { return okStatus(); }
511
  // ConnectionImpl
512
  Http::Status dispatch(Buffer::Instance& data) override;
513
  void onEncodeComplete() override;
514
689k
  StreamInfo::BytesMeter& getBytesMeter() override {
515
689k
    if (active_request_) {
516
658k
      return *(active_request_->response_encoder_.getStream().bytesMeter());
517
658k
    }
518
31.0k
    if (bytes_meter_before_stream_ == nullptr) {
519
30.9k
      bytes_meter_before_stream_ = std::make_shared<StreamInfo::BytesMeter>();
520
30.9k
    }
521
31.0k
    return *bytes_meter_before_stream_;
522
689k
  }
523
  Status onMessageBeginBase() override;
524
  Envoy::StatusOr<CallbackResult> onHeadersCompleteBase() override;
525
  // If upgrade behavior is not allowed, the HCM will have sanitized the headers out.
526
370
  bool upgradeAllowed() const override { return true; }
527
  void onBody(Buffer::Instance& data) override;
528
  void onResetStream(StreamResetReason reason) override;
529
  Status sendProtocolError(absl::string_view details) override;
530
  Status sendOverloadError();
531
  void onAboveHighWatermark() override;
532
  void onBelowLowWatermark() override;
533
652k
  HeaderMap& headersOrTrailers() override {
534
652k
    if (absl::holds_alternative<RequestHeaderMapPtr>(headers_or_trailers_)) {
535
638k
      return *absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
536
638k
    } else {
537
13.8k
      return *absl::get<RequestTrailerMapPtr>(headers_or_trailers_);
538
13.8k
    }
539
652k
  }
540
17.9k
  RequestOrResponseHeaderMap& requestOrResponseHeaders() override {
541
17.9k
    return *absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
542
17.9k
  }
543
27.9k
  void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) override {
544
27.9k
    ASSERT(nullptr == absl::get<RequestHeaderMapPtr>(headers_or_trailers_));
545
27.9k
    ASSERT(!processing_trailers_);
546
27.9k
    auto headers = RequestHeaderMapImpl::create(max_headers_kb_, max_headers_count_);
547
27.9k
    headers->setFormatter(std::move(formatter));
548
27.9k
    headers_or_trailers_.emplace<RequestHeaderMapPtr>(std::move(headers));
549
27.9k
  }
550
113
  void allocTrailers() override {
551
113
    ASSERT(processing_trailers_);
552
113
    if (!absl::holds_alternative<RequestTrailerMapPtr>(headers_or_trailers_)) {
553
113
      headers_or_trailers_.emplace<RequestTrailerMapPtr>(
554
113
          RequestTrailerMapImpl::create(max_headers_kb_, max_headers_count_));
555
113
    }
556
113
  }
557
  void dumpAdditionalState(std::ostream& os, int indent_level) const override;
558
559
  void releaseOutboundResponse(const Buffer::OwnedBufferFragmentImpl* fragment);
560
  void maybeAddSentinelBufferFragment(Buffer::Instance& output_buffer) override;
561
562
  Status doFloodProtectionChecks() const;
563
  Status checkHeaderNameForUnderscores() override;
564
  Status checkProtocolVersion(RequestHeaderMap& headers);
565
566
  ServerConnectionCallbacks& callbacks_;
567
  std::unique_ptr<ActiveRequest> active_request_;
568
  const Buffer::OwnedBufferFragmentImpl::Releasor response_buffer_releasor_;
569
  uint32_t outbound_responses_{};
570
  // Buffer used to encode the HTTP message before moving it to the network connection's output
571
  // buffer. This buffer is always allocated, never nullptr.
572
  Buffer::InstancePtr owned_output_buffer_;
573
  // TODO(mattklein123): This should be a member of ActiveRequest but this change needs dedicated
574
  // thought as some of the reset and no header code paths make this difficult. Headers are
575
  // populated on message begin. Trailers are populated on the first parsed trailer field (if
576
  // trailers are enabled). The variant is reset to null headers on message complete for assertion
577
  // purposes.
578
  absl::variant<RequestHeaderMapPtr, RequestTrailerMapPtr> headers_or_trailers_;
579
  // The action to take when a request header name contains underscore characters.
580
  const envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
581
      headers_with_underscores_action_;
582
  Server::LoadShedPoint* abort_dispatch_{nullptr};
583
};
584
585
/**
586
 * Implementation of Http::ClientConnection for HTTP/1.1.
587
 */
588
class ClientConnectionImpl : public ClientConnection, public ConnectionImpl {
589
public:
590
  ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
591
                       ConnectionCallbacks& callbacks, const Http1Settings& settings,
592
                       const uint32_t max_response_headers_count,
593
                       bool passing_through_proxy = false);
594
  // Http::ClientConnection
595
  RequestEncoder& newStream(ResponseDecoder& response_decoder) override;
596
597
private:
598
  struct PendingResponse {
599
    PendingResponse(ConnectionImpl& connection, StreamInfo::BytesMeterSharedPtr&& bytes_meter,
600
                    ResponseDecoder* decoder)
601
11.6k
        : encoder_(connection, std::move(bytes_meter)), decoder_(decoder) {}
602
    RequestEncoderImpl encoder_;
603
    ResponseDecoder* decoder_;
604
  };
605
606
  bool cannotHaveBody();
607
608
11.4k
  bool sendFullyQualifiedUrl() const override {
609
    // Send fully qualified URLs either if the parent connection is configured to do so or this
610
    // stream is passing through a proxy and the underlying transport is plaintext.
611
11.4k
    return ConnectionImpl::sendFullyQualifiedUrl() ||
612
11.4k
           (passing_through_proxy_ && !connection().ssl());
613
11.4k
  }
614
615
  // ParserCallbacks.
616
0
  Status onUrlBase(const char*, size_t) override { return okStatus(); }
617
  Status onStatusBase(const char* data, size_t length) override;
618
  // ConnectionImpl
619
  Http::Status dispatch(Buffer::Instance& data) override;
620
6.24k
  void onEncodeComplete() override {}
621
136k
  StreamInfo::BytesMeter& getBytesMeter() override {
622
136k
    if (pending_response_.has_value()) {
623
96.6k
      return *(pending_response_->encoder_.getStream().bytesMeter());
624
96.6k
    }
625
39.3k
    if (bytes_meter_before_stream_ == nullptr) {
626
18.5k
      bytes_meter_before_stream_ = std::make_shared<StreamInfo::BytesMeter>();
627
18.5k
    }
628
39.3k
    return *bytes_meter_before_stream_;
629
136k
  }
630
14.4k
  Status onMessageBeginBase() override { return okStatus(); }
631
  Envoy::StatusOr<CallbackResult> onHeadersCompleteBase() override;
632
  bool upgradeAllowed() const override;
633
  void onBody(Buffer::Instance& data) override;
634
  CallbackResult onMessageCompleteBase() override;
635
  void onResetStream(StreamResetReason reason) override;
636
  Status sendProtocolError(absl::string_view details) override;
637
  void onAboveHighWatermark() override;
638
  void onBelowLowWatermark() override;
639
105k
  HeaderMap& headersOrTrailers() override {
640
105k
    if (absl::holds_alternative<ResponseHeaderMapPtr>(headers_or_trailers_)) {
641
105k
      return *absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
642
105k
    } else {
643
0
      return *absl::get<ResponseTrailerMapPtr>(headers_or_trailers_);
644
0
    }
645
105k
  }
646
11.9k
  RequestOrResponseHeaderMap& requestOrResponseHeaders() override {
647
11.9k
    return *absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
648
11.9k
  }
649
14.4k
  void allocHeaders(StatefulHeaderKeyFormatterPtr&& formatter) override {
650
14.4k
    ASSERT(nullptr == absl::get<ResponseHeaderMapPtr>(headers_or_trailers_));
651
14.4k
    ASSERT(!processing_trailers_);
652
14.4k
    auto headers = ResponseHeaderMapImpl::create(max_headers_kb_, max_headers_count_);
653
14.4k
    headers->setFormatter(std::move(formatter));
654
14.4k
    headers_or_trailers_.emplace<ResponseHeaderMapPtr>(std::move(headers));
655
14.4k
  }
656
0
  void allocTrailers() override {
657
0
    ASSERT(processing_trailers_);
658
0
    if (!absl::holds_alternative<ResponseTrailerMapPtr>(headers_or_trailers_)) {
659
0
      headers_or_trailers_.emplace<ResponseTrailerMapPtr>(
660
0
          ResponseTrailerMapImpl::create(max_headers_kb_, max_headers_count_));
661
0
    }
662
0
  }
663
  void dumpAdditionalState(std::ostream& os, int indent_level) const override;
664
665
  // Buffer used to encode the HTTP message before moving it to the network connection's output
666
  // buffer. This buffer is always allocated, never nullptr.
667
  Buffer::InstancePtr owned_output_buffer_;
668
669
  absl::optional<PendingResponse> pending_response_;
670
  // TODO(mattklein123): The following bool tracks whether a pending response is complete before
671
  // dispatching callbacks. This is needed so that pending_response_ stays valid during callbacks
672
  // in order to access the stream, but to avoid invoking callbacks that shouldn't be called once
673
  // the response is complete. The existence of this variable is hard to reason about and it should
674
  // be combined with pending_response_ somehow in a follow up cleanup.
675
  bool pending_response_done_{true};
676
  // Set true between receiving non-101 1xx headers and receiving the spurious onMessageComplete.
677
  bool ignore_message_complete_for_1xx_{};
678
  // TODO(mattklein123): This should be a member of PendingResponse but this change needs dedicated
679
  // thought as some of the reset and no header code paths make this difficult. Headers are
680
  // populated on message begin. Trailers are populated when the switch to trailer processing is
681
  // detected while parsing the first trailer field (if trailers are enabled). The variant is reset
682
  // to null headers on message complete for assertion purposes.
683
  absl::variant<ResponseHeaderMapPtr, ResponseTrailerMapPtr> headers_or_trailers_;
684
685
  // True if the upstream connection is pointed at an HTTP/1.1 proxy, and
686
  // plaintext HTTP should be sent with fully qualified URLs.
687
  bool passing_through_proxy_ = false;
688
};
689
690
} // namespace Http1
691
} // namespace Http
692
} // namespace Envoy