LCOV - code coverage report
Current view: top level - source/common/http/http1 - codec_impl.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 824 1077 76.5 %
Date: 2024-01-05 06:35:25 Functions: 80 101 79.2 %

          Line data    Source code
       1             : #include "source/common/http/http1/codec_impl.h"
       2             : 
       3             : #include <cstdint>
       4             : #include <memory>
       5             : #include <string>
       6             : 
       7             : #include "envoy/buffer/buffer.h"
       8             : #include "envoy/common/optref.h"
       9             : #include "envoy/http/codec.h"
      10             : #include "envoy/http/header_map.h"
      11             : #include "envoy/network/connection.h"
      12             : 
      13             : #include "source/common/common/cleanup.h"
      14             : #include "source/common/common/dump_state_utils.h"
      15             : #include "source/common/common/enum_to_int.h"
      16             : #include "source/common/common/scope_tracker.h"
      17             : #include "source/common/common/statusor.h"
      18             : #include "source/common/common/utility.h"
      19             : #include "source/common/grpc/common.h"
      20             : #include "source/common/http/exception.h"
      21             : #include "source/common/http/header_utility.h"
      22             : #include "source/common/http/headers.h"
      23             : #include "source/common/http/http1/balsa_parser.h"
      24             : #include "source/common/http/http1/header_formatter.h"
      25             : #include "source/common/http/http1/legacy_parser_impl.h"
      26             : #include "source/common/http/utility.h"
      27             : #include "source/common/runtime/runtime_features.h"
      28             : 
      29             : #include "absl/container/fixed_array.h"
      30             : #include "absl/strings/ascii.h"
      31             : 
      32             : namespace Envoy {
      33             : namespace Http {
      34             : namespace Http1 {
      35             : namespace {
      36             : 
      37             : // Changes or additions to details should be reflected in
      38             : // docs/root/configuration/http/http_conn_man/response_code_details.rst
      39             : struct Http1ResponseCodeDetailValues {
      40             :   const absl::string_view TooManyHeaders = "http1.too_many_headers";
      41             :   const absl::string_view HeadersTooLarge = "http1.headers_too_large";
      42             :   const absl::string_view HttpCodecError = "http1.codec_error";
      43             :   const absl::string_view InvalidCharacters = "http1.invalid_characters";
      44             :   const absl::string_view ConnectionHeaderSanitization = "http1.connection_header_rejected";
      45             :   const absl::string_view InvalidUrl = "http1.invalid_url";
      46             :   const absl::string_view InvalidTransferEncoding = "http1.invalid_transfer_encoding";
      47             :   const absl::string_view BodyDisallowed = "http1.body_disallowed";
      48             :   const absl::string_view TransferEncodingNotAllowed = "http1.transfer_encoding_not_allowed";
      49             :   const absl::string_view ContentLengthNotAllowed = "http1.content_length_not_allowed";
      50             :   const absl::string_view InvalidUnderscore = "http1.unexpected_underscore";
      51             :   const absl::string_view ChunkedContentLength = "http1.content_length_and_chunked_not_allowed";
      52             :   const absl::string_view HttpsInPlaintext = "http1.https_url_on_plaintext_connection";
      53             :   const absl::string_view InvalidScheme = "http1.invalid_scheme";
      54             : };
      55             : 
      56             : struct Http1HeaderTypesValues {
      57             :   const absl::string_view Headers = "headers";
      58             :   const absl::string_view Trailers = "trailers";
      59             : };
      60             : 
      61             : // Pipelining is generally not well supported on the internet and has a series of dangerous
      62             : // overflow bugs. As such Envoy disabled it.
      63             : static constexpr uint32_t kMaxOutboundResponses = 2;
      64             : 
      65             : using Http1ResponseCodeDetails = ConstSingleton<Http1ResponseCodeDetailValues>;
      66             : using Http1HeaderTypes = ConstSingleton<Http1HeaderTypesValues>;
      67             : 
      68           0 : const StringUtil::CaseUnorderedSet& caseUnorderdSetContainingUpgradeAndHttp2Settings() {
      69           0 :   CONSTRUCT_ON_FIRST_USE(StringUtil::CaseUnorderedSet,
      70           0 :                          Http::Headers::get().ConnectionValues.Upgrade,
      71           0 :                          Http::Headers::get().ConnectionValues.Http2Settings);
      72           0 : }
      73             : 
      74        3112 : HeaderKeyFormatterConstPtr encodeOnlyFormatterFromSettings(const Http::Http1Settings& settings) {
      75        3112 :   if (settings.header_key_format_ == Http1Settings::HeaderKeyFormat::ProperCase) {
      76           0 :     return std::make_unique<ProperCaseHeaderKeyFormatter>();
      77           0 :   }
      78             : 
      79        3112 :   return nullptr;
      80        3112 : }
      81             : 
      82        1975 : StatefulHeaderKeyFormatterPtr statefulFormatterFromSettings(const Http::Http1Settings& settings) {
      83        1975 :   if (settings.header_key_format_ == Http1Settings::HeaderKeyFormat::StatefulFormatter) {
      84           0 :     return settings.stateful_header_key_formatter_->create();
      85           0 :   }
      86        1975 :   return nullptr;
      87        1975 : }
      88             : 
      89             : constexpr size_t CRLF_SIZE = 2;
      90             : 
      91             : } // namespace
      92             : 
      93             : static constexpr absl::string_view CRLF = "\r\n";
      94             : // Last chunk as defined here https://tools.ietf.org/html/rfc7230#section-4.1
      95             : static constexpr absl::string_view LAST_CHUNK = "0\r\n";
      96             : 
      97             : static constexpr absl::string_view SPACE = " ";
      98             : static constexpr absl::string_view COLON_SPACE = ": ";
      99             : 
     100             : StreamEncoderImpl::StreamEncoderImpl(ConnectionImpl& connection,
     101             :                                      StreamInfo::BytesMeterSharedPtr&& bytes_meter)
     102             :     : connection_(connection), disable_chunk_encoding_(false), chunk_encoding_(true),
     103             :       connect_request_(false), is_tcp_tunneling_(false), is_response_to_head_request_(false),
     104        1862 :       is_response_to_connect_request_(false), bytes_meter_(std::move(bytes_meter)) {
     105        1862 :   if (!bytes_meter_) {
     106         220 :     bytes_meter_ = std::make_shared<StreamInfo::BytesMeter>();
     107         220 :   }
     108        1862 :   if (connection_.connection().aboveHighWatermark()) {
     109           0 :     runHighWatermarkCallbacks();
     110           0 :   }
     111        1862 : }
     112             : 
     113        2637 : void StreamEncoderImpl::encodeHeader(absl::string_view key, absl::string_view value) {
     114        2637 :   ASSERT(!key.empty());
     115             : 
     116        2637 :   const uint64_t header_size = connection_.buffer().addFragments({key, COLON_SPACE, value, CRLF});
     117             : 
     118        2637 :   bytes_meter_->addHeaderBytesSent(header_size);
     119        2637 : }
     120             : 
     121             : void StreamEncoderImpl::encodeFormattedHeader(absl::string_view key, absl::string_view value,
     122        2637 :                                               HeaderKeyFormatterOptConstRef formatter) {
     123        2637 :   if (formatter.has_value()) {
     124           0 :     encodeHeader(formatter->format(key), value);
     125        2637 :   } else {
     126        2637 :     encodeHeader(key, value);
     127        2637 :   }
     128        2637 : }
     129             : 
     130          13 : void ResponseEncoderImpl::encode1xxHeaders(const ResponseHeaderMap& headers) {
     131          13 :   ASSERT(HeaderUtility::isSpecial1xx(headers));
     132          13 :   encodeHeaders(headers, false);
     133          13 :   if (Runtime::runtimeFeatureEnabled(
     134          13 :           "envoy.reloadable_features.http1_allow_codec_error_response_after_1xx_headers")) {
     135             :     // Don't consider 100-continue responses as the actual response.
     136          13 :     started_response_ = false;
     137          13 :   }
     138          13 : }
     139             : 
     140             : void StreamEncoderImpl::encodeHeadersBase(const RequestOrResponseHeaderMap& headers,
     141             :                                           absl::optional<uint64_t> status, bool end_stream,
     142         597 :                                           bool bodiless_request) {
     143         597 :   HeaderKeyFormatterOptConstRef formatter(headers.formatter());
     144         597 :   if (!formatter.has_value()) {
     145         597 :     formatter = connection_.formatter();
     146         597 :   }
     147             : 
     148         597 :   const Http::HeaderValues& header_values = Http::Headers::get();
     149         597 :   bool saw_content_length = false;
     150         597 :   headers.iterate(
     151        3379 :       [this, &header_values, formatter](const HeaderEntry& header) -> HeaderMap::Iterate {
     152        3379 :         absl::string_view key_to_use = header.key().getStringView();
     153        3379 :         uint32_t key_size_to_use = header.key().size();
     154             :         // Translate :authority -> host so that upper layers do not need to deal with this.
     155        3379 :         if (key_size_to_use > 1 && key_to_use[0] == ':' && key_to_use[1] == 'a') {
     156         212 :           key_to_use = absl::string_view(header_values.HostLegacy.get());
     157         212 :           key_size_to_use = header_values.HostLegacy.get().size();
     158         212 :         }
     159             : 
     160             :         // Skip all headers starting with ':' that make it here.
     161        3379 :         if (key_to_use[0] == ':') {
     162         995 :           return HeaderMap::Iterate::Continue;
     163         995 :         }
     164             : 
     165        2384 :         encodeFormattedHeader(key_to_use, header.value().getStringView(), formatter);
     166             : 
     167        2384 :         return HeaderMap::Iterate::Continue;
     168        3379 :       });
     169             : 
     170         597 :   if (headers.ContentLength()) {
     171         222 :     saw_content_length = true;
     172         222 :   }
     173             : 
     174         597 :   ASSERT(!headers.TransferEncoding());
     175             : 
     176             :   // Assume we are chunk encoding unless we are passed a content length or this is a header only
     177             :   // response. Upper layers generally should strip transfer-encoding since it only applies to
     178             :   // HTTP/1.1. The codec will infer it based on the type of response.
     179             :   // for streaming (e.g. SSE stream sent to hystrix dashboard), we do not want
     180             :   // chunk transfer encoding but we don't have a content-length so disable_chunk_encoding_ is
     181             :   // consulted before enabling chunk encoding.
     182             :   //
     183             :   // Note that for HEAD requests Envoy does best-effort guessing when there is no
     184             :   // content-length. If a client makes a HEAD request for an upstream resource
     185             :   // with no bytes but the upstream response doesn't include "Content-length: 0",
     186             :   // Envoy will incorrectly assume a subsequent response to GET will be chunk encoded.
     187         597 :   if (saw_content_length || disable_chunk_encoding_) {
     188         224 :     chunk_encoding_ = false;
     189         528 :   } else {
     190         373 :     if (status && (*status < 200 || *status == 204)) {
     191             :       // For 1xx and 204 responses, do not send the chunked encoding header or enable chunked
     192             :       // encoding: https://tools.ietf.org/html/rfc7230#section-3.3.1
     193          16 :       chunk_encoding_ = false;
     194         357 :     } else if (status && *status == 304) {
     195             :       // For 304 response, since it should never have a body, we should not need to chunk_encode at
     196             :       // all.
     197           0 :       chunk_encoding_ = false;
     198         357 :     } else if (end_stream && !is_response_to_head_request_) {
     199             :       // If this is a headers-only stream, append an explicit "Content-Length: 0" unless it's a
     200             :       // response to a HEAD request.
     201             :       // For 204s and 1xx where content length is disallowed, don't append the content length but
     202             :       // also don't chunk encode.
     203             :       // Also do not add content length for requests which should not have a
     204             :       // body, per https://tools.ietf.org/html/rfc7230#section-3.3.2
     205         116 :       if (!status || (*status >= 200 && *status != 204)) {
     206         116 :         if (!bodiless_request) {
     207          13 :           encodeFormattedHeader(header_values.ContentLength.get(), "0", formatter);
     208          13 :         }
     209         116 :       }
     210         116 :       chunk_encoding_ = false;
     211         243 :     } else if (connection_.protocol() == Protocol::Http10) {
     212           1 :       chunk_encoding_ = false;
     213         240 :     } else {
     214             :       // For responses to connect requests, do not send the chunked encoding header:
     215             :       // https://tools.ietf.org/html/rfc7231#section-4.3.6.
     216         240 :       if (!is_response_to_connect_request_) {
     217         240 :         encodeFormattedHeader(header_values.TransferEncoding.get(),
     218         240 :                               header_values.TransferEncodingValues.Chunked, formatter);
     219         240 :       }
     220             :       // We do not apply chunk encoding for HTTP upgrades, including CONNECT style upgrades.
     221             :       // If there is a body in a response on the upgrade path, the chunks will be
     222             :       // passed through via maybeDirectDispatch so we need to avoid appending
     223             :       // extra chunk boundaries.
     224             :       //
     225             :       // When sending a response to a HEAD request Envoy may send an informational
     226             :       // "Transfer-Encoding: chunked" header, but should not send a chunk encoded body.
     227         240 :       chunk_encoding_ = !Utility::isUpgrade(headers) && !is_response_to_head_request_ &&
     228         240 :                         !is_response_to_connect_request_;
     229         240 :     }
     230         373 :   }
     231             : 
     232         597 :   connection_.buffer().add(CRLF);
     233             : 
     234         597 :   if (end_stream) {
     235         117 :     endEncode();
     236         480 :   } else {
     237         480 :     flushOutput();
     238         480 :   }
     239         597 : }
     240             : 
     241         504 : void StreamEncoderImpl::encodeData(Buffer::Instance& data, bool end_stream) {
     242             :   // end_stream may be indicated with a zero length data buffer. If that is the case, so not
     243             :   // actually write the zero length buffer out.
     244         504 :   if (data.length() > 0) {
     245         461 :     if (chunk_encoding_) {
     246         236 :       std::string chunk_header = absl::StrCat(absl::Hex(data.length()), CRLF);
     247         236 :       connection_.buffer().add(std::move(chunk_header));
     248         236 :     }
     249             : 
     250         461 :     connection_.buffer().move(data);
     251             : 
     252         461 :     if (chunk_encoding_) {
     253         236 :       connection_.buffer().add(CRLF);
     254         236 :     }
     255         461 :   }
     256             : 
     257         504 :   if (end_stream) {
     258         401 :     endEncode();
     259         460 :   } else {
     260         103 :     flushOutput();
     261         103 :   }
     262         504 : }
     263             : 
     264        1118 : void StreamEncoderImpl::flushOutput(bool end_encode) {
     265        1118 :   auto encoded_bytes = connection_.flushOutput(end_encode);
     266        1118 :   bytes_meter_->addWireBytesSent(encoded_bytes);
     267        1118 : }
     268             : 
     269          17 : void StreamEncoderImpl::encodeTrailersBase(const HeaderMap& trailers) {
     270          17 :   if (!connection_.enableTrailers()) {
     271          17 :     return endEncode();
     272          17 :   }
     273             :   // Trailers only matter if it is a chunk transfer encoding
     274             :   // https://tools.ietf.org/html/rfc7230#section-4.4
     275           0 :   if (chunk_encoding_) {
     276             :     // Finalize the body
     277           0 :     connection_.buffer().add(LAST_CHUNK);
     278             : 
     279             :     // TODO(mattklein123): Wire up the formatter if someone actually asks for this (very unlikely).
     280           0 :     trailers.iterate([this](const HeaderEntry& header) -> HeaderMap::Iterate {
     281           0 :       encodeFormattedHeader(header.key().getStringView(), header.value().getStringView(),
     282           0 :                             HeaderKeyFormatterOptConstRef());
     283           0 :       return HeaderMap::Iterate::Continue;
     284           0 :     });
     285             : 
     286           0 :     connection_.buffer().add(CRLF);
     287           0 :   }
     288             : 
     289           0 :   flushOutput();
     290           0 :   notifyEncodeComplete();
     291           0 : }
     292             : 
     293           6 : void StreamEncoderImpl::encodeMetadata(const MetadataMapVector&) {
     294           6 :   connection_.stats().metadata_not_supported_error_.inc();
     295           6 : }
     296             : 
     297         535 : void StreamEncoderImpl::endEncode() {
     298         535 :   if (chunk_encoding_) {
     299         196 :     connection_.buffer().addFragments({LAST_CHUNK, CRLF});
     300         196 :   }
     301             : 
     302         535 :   flushOutput(true);
     303         535 :   notifyEncodeComplete();
     304             :   // With CONNECT or TCP tunneling, half-closing the connection is used to signal end stream so
     305             :   // don't delay that signal.
     306         535 :   if (connect_request_ || is_tcp_tunneling_) {
     307           0 :     connection_.connection().close(
     308           0 :         Network::ConnectionCloseType::FlushWrite,
     309           0 :         StreamInfo::LocalCloseReasons::get().CloseForConnectRequestOrTcpTunneling);
     310           0 :   }
     311         535 : }
     312             : 
     313         535 : void StreamEncoderImpl::notifyEncodeComplete() {
     314         535 :   if (codec_callbacks_) {
     315         352 :     codec_callbacks_->onCodecEncodeComplete();
     316         352 :   }
     317         535 :   connection_.onEncodeComplete();
     318         535 : }
     319             : 
     320         367 : void ServerConnectionImpl::maybeAddSentinelBufferFragment(Buffer::Instance& output_buffer) {
     321             :   // It's messy and complicated to try to tag the final write of an HTTP response for response
     322             :   // tracking for flood protection. Instead, write an empty buffer fragment after the response,
     323             :   // to allow for tracking.
     324             :   // When the response is written out, the fragment will be deleted and the counter will be updated
     325             :   // by ServerConnectionImpl::releaseOutboundResponse()
     326         367 :   auto fragment =
     327         367 :       Buffer::OwnedBufferFragmentImpl::create(absl::string_view("", 0), response_buffer_releasor_);
     328         367 :   output_buffer.addBufferFragment(*fragment.release());
     329         367 :   ASSERT(outbound_responses_ < kMaxOutboundResponses);
     330         367 :   outbound_responses_++;
     331         367 : }
     332             : 
     333        1642 : Status ServerConnectionImpl::doFloodProtectionChecks() const {
     334        1642 :   ASSERT(dispatching_);
     335             :   // Before processing another request, make sure that we are below the response flood protection
     336             :   // threshold.
     337        1642 :   if (outbound_responses_ >= kMaxOutboundResponses) {
     338           0 :     ENVOY_CONN_LOG(trace, "error accepting request: too many pending responses queued",
     339           0 :                    connection_);
     340           0 :     stats_.response_flood_.inc();
     341           0 :     return bufferFloodError("Too many responses queued.");
     342           0 :   }
     343        1642 :   return okStatus();
     344        1642 : }
     345             : 
     346        1118 : uint64_t ConnectionImpl::flushOutput(bool end_encode) {
     347        1118 :   if (end_encode) {
     348             :     // If this is an HTTP response in ServerConnectionImpl, track outbound responses for flood
     349             :     // protection
     350         535 :     maybeAddSentinelBufferFragment(*output_buffer_);
     351         535 :   }
     352        1118 :   const uint64_t bytes_encoded = output_buffer_->length();
     353        1118 :   connection().write(*output_buffer_, false);
     354        1118 :   ASSERT(0UL == output_buffer_->length());
     355        1118 :   return bytes_encoded;
     356        1118 : }
     357             : 
     358             : CodecEventCallbacks*
     359         806 : StreamEncoderImpl::registerCodecEventCallbacks(CodecEventCallbacks* codec_callbacks) {
     360         806 :   std::swap(codec_callbacks, codec_callbacks_);
     361         806 :   return codec_callbacks;
     362         806 : }
     363             : 
     364         247 : void StreamEncoderImpl::resetStream(StreamResetReason reason) {
     365         247 :   connection_.onResetStreamBase(reason);
     366         247 : }
     367             : 
     368         215 : void ResponseEncoderImpl::resetStream(StreamResetReason reason) {
     369             :   // Clear the downstream on the account since we're resetting the downstream.
     370         215 :   if (buffer_memory_account_) {
     371           0 :     buffer_memory_account_->clearDownstream();
     372           0 :   }
     373             : 
     374             :   // For H1, we use idleTimeouts to cancel streams unless there was an
     375             :   // explicit protocol error prior to sending a response to the downstream
     376             :   // in which case we send a local reply.
     377             :   // TODO(kbaichoo): If we want snappier resets of H1 streams we can
     378             :   //  1) Send local reply if no response data sent yet
     379             :   //  2) Invoke the idle timeout sooner to close underlying connection
     380         215 :   StreamEncoderImpl::resetStream(reason);
     381         215 : }
     382             : 
     383         142 : void StreamEncoderImpl::readDisable(bool disable) {
     384         142 :   if (disable) {
     385          71 :     ++read_disable_calls_;
     386          71 :   } else {
     387          71 :     ASSERT(read_disable_calls_ != 0);
     388          71 :     if (read_disable_calls_ != 0) {
     389          71 :       --read_disable_calls_;
     390          71 :     }
     391          71 :   }
     392         142 :   connection_.readDisable(disable);
     393         142 : }
     394             : 
     395         403 : uint32_t StreamEncoderImpl::bufferLimit() const { return connection_.bufferLimit(); }
     396             : 
     397          54 : const Network::ConnectionInfoProvider& StreamEncoderImpl::connectionInfoProvider() {
     398          54 :   return connection_.connection().connectionInfoProvider();
     399          54 : }
     400             : 
     401             : static constexpr absl::string_view RESPONSE_PREFIX = "HTTP/1.1 ";
     402             : static constexpr absl::string_view HTTP_10_RESPONSE_PREFIX = "HTTP/1.0 ";
     403             : 
     404         385 : void ResponseEncoderImpl::encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) {
     405         385 :   started_response_ = true;
     406             : 
     407             :   // The contract is that client codecs must ensure that :status is present and valid.
     408         385 :   ASSERT(headers.Status() != nullptr);
     409         385 :   uint64_t numeric_status = Utility::getResponseStatus(headers);
     410             : 
     411         385 :   absl::string_view response_prefix;
     412         385 :   if (connection_.protocol() == Protocol::Http10 && connection_.supportsHttp10()) {
     413           1 :     response_prefix = HTTP_10_RESPONSE_PREFIX;
     414         384 :   } else {
     415         384 :     response_prefix = RESPONSE_PREFIX;
     416         384 :   }
     417             : 
     418         385 :   StatefulHeaderKeyFormatterOptConstRef formatter(headers.formatter());
     419             : 
     420         385 :   absl::string_view reason_phrase;
     421         385 :   if (formatter.has_value() && !formatter->getReasonPhrase().empty()) {
     422           0 :     reason_phrase = formatter->getReasonPhrase();
     423         385 :   } else {
     424         385 :     const char* status_string = CodeUtility::toString(static_cast<Code>(numeric_status));
     425         385 :     uint32_t status_string_len = strlen(status_string);
     426         385 :     reason_phrase = {status_string, status_string_len};
     427         385 :   }
     428             : 
     429         385 :   connection_.buffer().addFragments(
     430         385 :       {response_prefix, absl::StrCat(numeric_status), SPACE, reason_phrase, CRLF});
     431             : 
     432         385 :   if (numeric_status >= 300) {
     433             :     // Don't do special CONNECT logic if the CONNECT was rejected.
     434         102 :     is_response_to_connect_request_ = false;
     435         102 :   }
     436             : 
     437         385 :   encodeHeadersBase(headers, absl::make_optional<uint64_t>(numeric_status), end_stream, false);
     438         385 : }
     439             : 
     440             : static constexpr absl::string_view REQUEST_POSTFIX = " HTTP/1.1\r\n";
     441             : 
     442         220 : Status RequestEncoderImpl::encodeHeaders(const RequestHeaderMap& headers, bool end_stream) {
     443         220 : #ifndef ENVOY_ENABLE_UHV
     444             :   // Headers are now validated by UHV before encoding by the codec. Two checks below are not needed
     445             :   // when UHV is enabled.
     446             :   //
     447             :   // Required headers must be present. This can only happen by some erroneous processing after the
     448             :   // downstream codecs decode.
     449         220 :   RETURN_IF_ERROR(HeaderUtility::checkRequiredRequestHeaders(headers));
     450             :   // Verify that a filter hasn't added an invalid header key or value.
     451         217 :   RETURN_IF_ERROR(HeaderUtility::checkValidRequestHeaders(headers));
     452         212 : #endif
     453             : 
     454         212 :   const HeaderEntry* method = headers.Method();
     455         212 :   const HeaderEntry* path = headers.Path();
     456         212 :   const HeaderEntry* host = headers.Host();
     457         212 :   bool is_connect = HeaderUtility::isConnect(headers);
     458         212 :   const Http::HeaderValues& header_values = Http::Headers::get();
     459             : 
     460         212 :   if (method->value() == header_values.MethodValues.Head) {
     461           2 :     head_request_ = true;
     462         210 :   } else if (method->value() == header_values.MethodValues.Connect) {
     463           0 :     disableChunkEncoding();
     464           0 :     connection_.connection().enableHalfClose(true);
     465           0 :     connect_request_ = true;
     466           0 :   }
     467         212 :   if (Utility::isUpgrade(headers)) {
     468           2 :     upgrade_request_ = true;
     469             :     // If the flag is flipped from true to false all outstanding upgrade requests that are waiting
     470             :     // for upstream connections will become invalid, as Envoy will add chunk encoding to the
     471             :     // protocol stream. This will likely cause the server to disconnect, since it will be unable to
     472             :     // parse the protocol.
     473           2 :     disableChunkEncoding();
     474           2 :   }
     475             : 
     476         212 :   if (connection_.sendFullyQualifiedUrl() && !is_connect) {
     477           0 :     const HeaderEntry* scheme = headers.Scheme();
     478           0 :     if (!scheme) {
     479           0 :       return absl::InvalidArgumentError(
     480           0 :           absl::StrCat("missing required header: ", Envoy::Http::Headers::get().Scheme.get()));
     481           0 :     }
     482           0 :     if (!host) {
     483           0 :       return absl::InvalidArgumentError(
     484           0 :           absl::StrCat("missing required header: ", Envoy::Http::Headers::get().Host.get()));
     485           0 :     }
     486           0 :     ASSERT(path);
     487           0 :     ASSERT(host);
     488             : 
     489           0 :     std::string url = absl::StrCat(scheme->value().getStringView(), "://",
     490           0 :                                    host->value().getStringView(), path->value().getStringView());
     491           0 :     ENVOY_CONN_LOG(trace, "Sending fully qualified URL: {}", connection_.connection(), url);
     492           0 :     connection_.buffer().addFragments(
     493           0 :         {method->value().getStringView(), SPACE, url, REQUEST_POSTFIX});
     494         212 :   } else {
     495         212 :     absl::string_view host_or_path_view;
     496         212 :     if (is_connect) {
     497           0 :       host_or_path_view = host->value().getStringView();
     498         212 :     } else {
     499         212 :       host_or_path_view = path->value().getStringView();
     500         212 :     }
     501             : 
     502         212 :     connection_.buffer().addFragments(
     503         212 :         {method->value().getStringView(), SPACE, host_or_path_view, REQUEST_POSTFIX});
     504         212 :   }
     505             : 
     506         212 :   encodeHeadersBase(headers, absl::nullopt, end_stream,
     507         212 :                     HeaderUtility::requestShouldHaveNoBody(headers));
     508         212 :   return okStatus();
     509         212 : }
     510             : 
     511        8191 : CallbackResult ConnectionImpl::setAndCheckCallbackStatus(Status&& status) {
     512        8191 :   ASSERT(codec_status_.ok());
     513        8191 :   codec_status_ = std::move(status);
     514        8191 :   return codec_status_.ok() ? CallbackResult::Success : CallbackResult::Error;
     515        8191 : }
     516             : 
     517             : CallbackResult
     518        1044 : ConnectionImpl::setAndCheckCallbackStatusOr(Envoy::StatusOr<CallbackResult>&& statusor) {
     519        1044 :   ASSERT(codec_status_.ok());
     520        1044 :   if (statusor.ok()) {
     521         931 :     return statusor.value();
     522         931 :   } else {
     523         113 :     codec_status_ = std::move(statusor.status());
     524         113 :     return CallbackResult::Error;
     525         113 :   }
     526        1044 : }
     527             : 
     528             : ConnectionImpl::ConnectionImpl(Network::Connection& connection, CodecStats& stats,
     529             :                                const Http1Settings& settings, MessageType type,
     530             :                                uint32_t max_headers_kb, const uint32_t max_headers_count)
     531             :     : connection_(connection), stats_(stats), codec_settings_(settings),
     532             :       encode_only_header_key_formatter_(encodeOnlyFormatterFromSettings(settings)),
     533             :       processing_trailers_(false), handling_upgrade_(false), reset_stream_called_(false),
     534             :       deferred_end_stream_headers_(false), dispatching_(false), max_headers_kb_(max_headers_kb),
     535        3112 :       max_headers_count_(max_headers_count) {
     536        3112 :   if (codec_settings_.use_balsa_parser_) {
     537        1571 :     parser_ = std::make_unique<BalsaParser>(type, this, max_headers_kb_ * 1024, enableTrailers(),
     538        1571 :                                             codec_settings_.allow_custom_methods_);
     539        1849 :   } else {
     540        1541 :     parser_ = std::make_unique<LegacyHttpParserImpl>(type, this);
     541        1541 :   }
     542        3112 : }
     543             : 
     544        2480 : Status ConnectionImpl::completeCurrentHeader() {
     545        2480 :   ASSERT(dispatching_);
     546        2480 :   ENVOY_CONN_LOG(trace, "completed header: key={} value={}", connection_,
     547        2480 :                  current_header_field_.getStringView(), current_header_value_.getStringView());
     548        2480 :   auto& headers_or_trailers = headersOrTrailers();
     549             : 
     550             :   // Account for ":" and "\r\n" bytes between the header key value pair.
     551        2480 :   getBytesMeter().addHeaderBytesReceived(CRLF_SIZE + 1);
     552             : 
     553             :   // TODO(10646): Switch to use HeaderUtility::checkHeaderNameForUnderscores().
     554        2480 :   RETURN_IF_ERROR(checkHeaderNameForUnderscores());
     555        2480 :   if (!current_header_field_.empty()) {
     556             :     // Strip trailing whitespace of the current header value if any. Leading whitespace was trimmed
     557             :     // in ConnectionImpl::onHeaderValue. http_parser does not strip leading or trailing whitespace
     558             :     // as the spec requires: https://tools.ietf.org/html/rfc7230#section-3.2.4
     559        2407 :     current_header_value_.rtrim();
     560             : 
     561             :     // If there is a stateful formatter installed, remember the original header key before
     562             :     // converting to lower case.
     563        2407 :     auto formatter = headers_or_trailers.formatter();
     564        2407 :     if (formatter.has_value()) {
     565           0 :       formatter->processKey(current_header_field_.getStringView());
     566           0 :     }
     567       32451 :     current_header_field_.inlineTransform([](char c) { return absl::ascii_tolower(c); });
     568             : 
     569        2407 :     headers_or_trailers.addViaMove(std::move(current_header_field_),
     570        2407 :                                    std::move(current_header_value_));
     571        2407 :   }
     572             : 
     573             :   // Check if the number of headers exceeds the limit.
     574        2480 :   if (headers_or_trailers.size() > max_headers_count_) {
     575           0 :     error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
     576           0 :     RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().TooManyHeaders));
     577           0 :     const absl::string_view header_type =
     578           0 :         processing_trailers_ ? Http1HeaderTypes::get().Trailers : Http1HeaderTypes::get().Headers;
     579           0 :     return codecProtocolError(
     580           0 :         absl::StrCat("http/1.1 protocol error: ", header_type, " count exceeds limit"));
     581           0 :   }
     582             : 
     583        2480 :   header_parsing_state_ = HeaderParsingState::Field;
     584        2480 :   ASSERT(current_header_field_.empty());
     585        2480 :   ASSERT(current_header_value_.empty());
     586        2480 :   return okStatus();
     587        2480 : }
     588             : 
     589        1975 : Status ConnectionImpl::onMessageBeginImpl() {
     590        1975 :   ENVOY_CONN_LOG(trace, "message begin", connection_);
     591             :   // Make sure that if HTTP/1.0 and HTTP/1.1 requests share a connection Envoy correctly sets
     592             :   // protocol for each request. Envoy defaults to 1.1 but sets the protocol to 1.0 where applicable
     593             :   // in onHeadersCompleteBase
     594        1975 :   protocol_ = Protocol::Http11;
     595        1975 :   processing_trailers_ = false;
     596        1975 :   header_parsing_state_ = HeaderParsingState::Field;
     597        1975 :   allocHeaders(statefulFormatterFromSettings(codec_settings_));
     598        1975 :   return onMessageBeginBase();
     599        1975 : }
     600             : 
     601        6237 : uint32_t ConnectionImpl::getHeadersSize() {
     602        6237 :   return current_header_field_.size() + current_header_value_.size() +
     603        6237 :          headersOrTrailers().byteSize();
     604        6237 : }
     605             : 
     606        6237 : Status ConnectionImpl::checkMaxHeadersSize() {
     607        6237 :   const uint32_t total = getHeadersSize();
     608        6237 :   if (total > (max_headers_kb_ * 1024)) {
     609           0 :     const absl::string_view header_type =
     610           0 :         processing_trailers_ ? Http1HeaderTypes::get().Trailers : Http1HeaderTypes::get().Headers;
     611           0 :     error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
     612           0 :     RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().HeadersTooLarge));
     613           0 :     return codecProtocolError(
     614           0 :         absl::StrCat("http/1.1 protocol error: ", header_type, " size exceeds limit"));
     615           0 :   }
     616        6237 :   return okStatus();
     617        6237 : }
     618             : 
     619        4038 : bool ConnectionImpl::maybeDirectDispatch(Buffer::Instance& data) {
     620        4038 :   if (!handling_upgrade_) {
     621             :     // Only direct dispatch for Upgrade requests.
     622        4034 :     return false;
     623        4034 :   }
     624             : 
     625           4 :   ENVOY_CONN_LOG(trace, "direct-dispatched {} bytes", connection_, data.length());
     626           4 :   onBody(data);
     627           4 :   data.drain(data.length());
     628           4 :   return true;
     629        4038 : }
     630             : 
     631        3126 : void ConnectionImpl::onDispatch(const Buffer::Instance& data) {
     632        3126 :   getBytesMeter().addWireBytesReceived(data.length());
     633        3126 : }
     634             : 
     635        1398 : Http::Status ClientConnectionImpl::dispatch(Buffer::Instance& data) {
     636        1398 :   Http::Status status = ConnectionImpl::dispatch(data);
     637        1398 :   if (status.ok() && data.length() > 0) {
     638             :     // The HTTP/1.1 codec pauses dispatch after a single response is complete. Extraneous data
     639             :     // after a response is complete indicates an error.
     640           0 :     return codecProtocolError("http/1.1 protocol error: extraneous data after response complete");
     641           0 :   }
     642        1398 :   return status;
     643        1398 : }
     644             : 
     645        3126 : Http::Status ConnectionImpl::dispatch(Buffer::Instance& data) {
     646             :   // Add self to the Dispatcher's tracked object stack.
     647        3126 :   ScopeTrackerScopeState scope(this, connection_.dispatcher());
     648        3126 :   ENVOY_CONN_LOG(trace, "parsing {} bytes", connection_, data.length());
     649             :   // Make sure that dispatching_ is set to false after dispatching, even when
     650             :   // http_parser exits early with an error code.
     651        3126 :   Cleanup cleanup([this]() { dispatching_ = false; });
     652        3126 :   ASSERT(!dispatching_);
     653        3126 :   ASSERT(codec_status_.ok());
     654        3126 :   ASSERT(buffered_body_.length() == 0);
     655             : 
     656        3126 :   dispatching_ = true;
     657        3126 :   onDispatch(data);
     658        3126 :   if (maybeDirectDispatch(data)) {
     659           2 :     return Http::okStatus();
     660           2 :   }
     661             : 
     662             :   // Always resume before dispatch.
     663        3124 :   parser_->resume();
     664             : 
     665        3124 :   ssize_t total_parsed = 0;
     666        3124 :   if (data.length() > 0) {
     667        2955 :     current_dispatching_buffer_ = &data;
     668        3434 :     while (data.length() > 0) {
     669        3198 :       auto slice = data.frontSlice();
     670        3198 :       dispatching_slice_already_drained_ = false;
     671        3198 :       auto statusor_parsed = dispatchSlice(static_cast<const char*>(slice.mem_), slice.len_);
     672        3198 :       if (!statusor_parsed.ok()) {
     673        2212 :         return statusor_parsed.status();
     674        2212 :       }
     675         986 :       if (!dispatching_slice_already_drained_) {
     676         985 :         ASSERT(statusor_parsed.value() <= slice.len_);
     677         985 :         data.drain(statusor_parsed.value());
     678         985 :       }
     679             : 
     680         986 :       total_parsed += statusor_parsed.value();
     681         986 :       if (parser_->getStatus() != ParserStatus::Ok) {
     682             :         // Parse errors trigger an exception in dispatchSlice so we are guaranteed to be paused at
     683             :         // this point.
     684         507 :         ASSERT(parser_->getStatus() == ParserStatus::Paused);
     685         507 :         break;
     686         507 :       }
     687         986 :     }
     688         743 :     current_dispatching_buffer_ = nullptr;
     689         743 :     dispatchBufferedBody();
     690         743 :   } else {
     691         169 :     auto result = dispatchSlice(nullptr, 0);
     692         169 :     if (!result.ok()) {
     693           0 :       return result.status();
     694           0 :     }
     695         169 :   }
     696         912 :   ASSERT(buffered_body_.length() == 0);
     697             : 
     698         912 :   ENVOY_CONN_LOG(trace, "parsed {} bytes", connection_, total_parsed);
     699             : 
     700             :   // If an upgrade has been handled and there is body data or early upgrade
     701             :   // payload to send on, send it on.
     702         912 :   maybeDirectDispatch(data);
     703         912 :   return Http::okStatus();
     704        3124 : }
     705             : 
     706        3367 : Envoy::StatusOr<size_t> ConnectionImpl::dispatchSlice(const char* slice, size_t len) {
     707        3367 :   ASSERT(codec_status_.ok() && dispatching_);
     708        3367 :   const size_t nread = parser_->execute(slice, len);
     709        3367 :   if (!codec_status_.ok()) {
     710         115 :     return codec_status_;
     711         115 :   }
     712             : 
     713        3252 :   const ParserStatus status = parser_->getStatus();
     714        3252 :   if (status != ParserStatus::Ok && status != ParserStatus::Paused) {
     715        2097 :     absl::string_view error = Http1ResponseCodeDetails::get().HttpCodecError;
     716        2097 :     if (codec_settings_.use_balsa_parser_) {
     717         961 :       if (parser_->errorMessage() == "headers size exceeds limit" ||
     718         961 :           parser_->errorMessage() == "trailers size exceeds limit") {
     719           0 :         error_code_ = Http::Code::RequestHeaderFieldsTooLarge;
     720           0 :         error = Http1ResponseCodeDetails::get().HeadersTooLarge;
     721         961 :       } else if (parser_->errorMessage() == "header value contains invalid chars") {
     722          70 :         error = Http1ResponseCodeDetails::get().InvalidCharacters;
     723          70 :       }
     724         961 :     }
     725        2097 :     RETURN_IF_ERROR(sendProtocolError(error));
     726             :     // Avoid overwriting the codec_status_ set in the callbacks.
     727        2097 :     ASSERT(codec_status_.ok());
     728        2097 :     codec_status_ =
     729        2097 :         codecProtocolError(absl::StrCat("http/1.1 protocol error: ", parser_->errorMessage()));
     730        2097 :     return codec_status_;
     731        2097 :   }
     732             : 
     733        1155 :   return nread;
     734        3252 : }
     735             : 
     736        1796 : CallbackResult ConnectionImpl::onMessageBegin() {
     737        1796 :   return setAndCheckCallbackStatus(onMessageBeginImpl());
     738        1796 : }
     739             : 
     740        1032 : CallbackResult ConnectionImpl::onUrl(const char* data, size_t length) {
     741        1032 :   return setAndCheckCallbackStatus(onUrlBase(data, length));
     742        1032 : }
     743             : 
     744         156 : CallbackResult ConnectionImpl::onStatus(const char* data, size_t length) {
     745         156 :   return setAndCheckCallbackStatus(onStatusBase(data, length));
     746         156 : }
     747             : 
     748        2616 : CallbackResult ConnectionImpl::onHeaderField(const char* data, size_t length) {
     749        2616 :   return setAndCheckCallbackStatus(onHeaderFieldImpl(data, length));
     750        2616 : }
     751             : 
     752        2591 : CallbackResult ConnectionImpl::onHeaderValue(const char* data, size_t length) {
     753        2591 :   return setAndCheckCallbackStatus(onHeaderValueImpl(data, length));
     754        2591 : }
     755             : 
     756         649 : CallbackResult ConnectionImpl::onHeadersComplete() {
     757         649 :   return setAndCheckCallbackStatusOr(onHeadersCompleteImpl());
     758         649 : }
     759             : 
     760         363 : void ConnectionImpl::bufferBody(const char* data, size_t length) {
     761         363 :   auto slice = current_dispatching_buffer_->frontSlice();
     762         363 :   if (data == slice.mem_ && length == slice.len_) {
     763           1 :     buffered_body_.move(*current_dispatching_buffer_, length);
     764           1 :     dispatching_slice_already_drained_ = true;
     765         362 :   } else {
     766         362 :     buffered_body_.add(data, length);
     767         362 :   }
     768         363 : }
     769             : 
     770         395 : CallbackResult ConnectionImpl::onMessageComplete() {
     771         395 :   return setAndCheckCallbackStatusOr(onMessageCompleteImpl());
     772         395 : }
     773             : 
     774         471 : void ConnectionImpl::onChunkHeader(bool is_final_chunk) {
     775         471 :   if (is_final_chunk) {
     776             :     // Dispatch body before parsing trailers, so body ends up dispatched even if an error is found
     777             :     // while processing trailers.
     778         216 :     dispatchBufferedBody();
     779         216 :   }
     780         471 : }
     781             : 
     782        2616 : Status ConnectionImpl::onHeaderFieldImpl(const char* data, size_t length) {
     783        2616 :   ASSERT(dispatching_);
     784             : 
     785        2616 :   getBytesMeter().addHeaderBytesReceived(length);
     786             : 
     787             :   // We previously already finished up the headers, these headers are
     788             :   // now trailers.
     789        2616 :   if (header_parsing_state_ == HeaderParsingState::Done) {
     790           0 :     if (!enableTrailers()) {
     791             :       // Ignore trailers.
     792           0 :       return okStatus();
     793           0 :     }
     794           0 :     processing_trailers_ = true;
     795           0 :     header_parsing_state_ = HeaderParsingState::Field;
     796           0 :     allocTrailers();
     797           0 :   }
     798        2616 :   if (header_parsing_state_ == HeaderParsingState::Value) {
     799        1831 :     RETURN_IF_ERROR(completeCurrentHeader());
     800        1831 :   }
     801             : 
     802        2616 :   current_header_field_.append(data, length);
     803             : 
     804        2616 :   return checkMaxHeadersSize();
     805        2616 : }
     806             : 
     807        2591 : Status ConnectionImpl::onHeaderValueImpl(const char* data, size_t length) {
     808        2591 :   ASSERT(dispatching_);
     809             : 
     810        2591 :   getBytesMeter().addHeaderBytesReceived(length);
     811             : 
     812        2591 :   if (header_parsing_state_ == HeaderParsingState::Done && !enableTrailers()) {
     813             :     // Ignore trailers.
     814           0 :     return okStatus();
     815           0 :   }
     816             : 
     817        2591 :   absl::string_view header_value{data, length};
     818        2591 :   if (!Http::HeaderUtility::headerValueIsValid(header_value)) {
     819           2 :     ENVOY_CONN_LOG(debug, "invalid header value: {}", connection_, header_value);
     820           2 :     error_code_ = Http::Code::BadRequest;
     821           2 :     RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidCharacters));
     822           2 :     return codecProtocolError("http/1.1 protocol error: header value contains invalid chars");
     823           2 :   }
     824             : 
     825        2589 :   header_parsing_state_ = HeaderParsingState::Value;
     826        2589 :   if (current_header_value_.empty()) {
     827             :     // Strip leading whitespace if the current header value input contains the first bytes of the
     828             :     // encoded header value. Trailing whitespace is stripped once the full header value is known in
     829             :     // ConnectionImpl::completeCurrentHeader. http_parser does not strip leading or trailing
     830             :     // whitespace as the spec requires: https://tools.ietf.org/html/rfc7230#section-3.2.4 .
     831        2584 :     header_value = StringUtil::ltrim(header_value);
     832        2584 :   }
     833        2589 :   current_header_value_.append(header_value.data(), header_value.length());
     834             : 
     835        2589 :   return checkMaxHeadersSize();
     836        2591 : }
     837             : 
     838         649 : StatusOr<CallbackResult> ConnectionImpl::onHeadersCompleteImpl() {
     839         649 :   ASSERT(!processing_trailers_);
     840         649 :   ASSERT(dispatching_);
     841         649 :   ENVOY_CONN_LOG(trace, "onHeadersCompleteImpl", connection_);
     842         649 :   RETURN_IF_ERROR(completeCurrentHeader());
     843             : 
     844         649 :   if (!parser_->isHttp11()) {
     845             :     // This is not necessarily true, but it's good enough since higher layers only care if this is
     846             :     // HTTP/1.1 or not.
     847         101 :     protocol_ = Protocol::Http10;
     848         101 :   }
     849         649 :   RequestOrResponseHeaderMap& request_or_response_headers = requestOrResponseHeaders();
     850         649 :   const Http::HeaderValues& header_values = Http::Headers::get();
     851         649 :   if (Utility::isUpgrade(request_or_response_headers) && upgradeAllowed()) {
     852             :     // Ignore h2c upgrade requests until we support them.
     853             :     // See https://github.com/envoyproxy/envoy/issues/7161 for details.
     854           2 :     if (absl::EqualsIgnoreCase(request_or_response_headers.getUpgradeValue(),
     855           2 :                                header_values.UpgradeValues.H2c)) {
     856           0 :       ENVOY_CONN_LOG(trace, "removing unsupported h2c upgrade headers.", connection_);
     857           0 :       request_or_response_headers.removeUpgrade();
     858           0 :       if (request_or_response_headers.Connection()) {
     859           0 :         const auto& tokens_to_remove = caseUnorderdSetContainingUpgradeAndHttp2Settings();
     860           0 :         std::string new_value = StringUtil::removeTokens(
     861           0 :             request_or_response_headers.getConnectionValue(), ",", tokens_to_remove, ",");
     862           0 :         if (new_value.empty()) {
     863           0 :           request_or_response_headers.removeConnection();
     864           0 :         } else {
     865           0 :           request_or_response_headers.setConnection(new_value);
     866           0 :         }
     867           0 :       }
     868           0 :       request_or_response_headers.remove(header_values.Http2Settings);
     869           2 :     } else {
     870           2 :       ENVOY_CONN_LOG(trace, "codec entering upgrade mode.", connection_);
     871           2 :       handling_upgrade_ = true;
     872           2 :     }
     873           2 :   }
     874         649 :   if (parser_->methodName() == header_values.MethodValues.Connect) {
     875          46 :     if (request_or_response_headers.ContentLength()) {
     876           2 :       if (request_or_response_headers.getContentLengthValue() == "0") {
     877           0 :         request_or_response_headers.removeContentLength();
     878           2 :       } else {
     879             :         // Per https://tools.ietf.org/html/rfc7231#section-4.3.6 a payload with a
     880             :         // CONNECT request has no defined semantics, and may be rejected.
     881           2 :         error_code_ = Http::Code::BadRequest;
     882           2 :         RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().BodyDisallowed));
     883           2 :         return codecProtocolError("http/1.1 protocol error: unsupported content length");
     884           2 :       }
     885           2 :     }
     886          44 :     ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT request.", connection_);
     887          44 :     handling_upgrade_ = true;
     888          44 :   }
     889             : 
     890             :   // https://tools.ietf.org/html/rfc7230#section-3.3.3
     891             :   // If a message is received with both a Transfer-Encoding and a
     892             :   // Content-Length header field, the Transfer-Encoding overrides the
     893             :   // Content-Length. Such a message might indicate an attempt to
     894             :   // perform request smuggling (Section 9.5) or response splitting
     895             :   // (Section 9.4) and ought to be handled as an error. A sender MUST
     896             :   // remove the received Content-Length field prior to forwarding such
     897             :   // a message.
     898             : 
     899         647 : #ifndef ENVOY_ENABLE_UHV
     900             :   // This check is moved into default header validator.
     901             :   // TODO(yanavlasov): use runtime override here when UHV is moved into the main build
     902             : 
     903             :   // Reject message with Http::Code::BadRequest if both Transfer-Encoding and Content-Length
     904             :   // headers are present or if allowed by http1 codec settings and 'Transfer-Encoding'
     905             :   // is chunked - remove Content-Length and serve request.
     906         647 :   if (parser_->hasTransferEncoding() != 0 && request_or_response_headers.ContentLength()) {
     907           8 :     if (parser_->isChunked() && codec_settings_.allow_chunked_length_) {
     908           0 :       request_or_response_headers.removeContentLength();
     909           8 :     } else {
     910           8 :       error_code_ = Http::Code::BadRequest;
     911           8 :       RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().ChunkedContentLength));
     912           8 :       return codecProtocolError(
     913           8 :           "http/1.1 protocol error: both 'Content-Length' and 'Transfer-Encoding' are set.");
     914           8 :     }
     915           8 :   }
     916             : 
     917             :   // Per https://tools.ietf.org/html/rfc7230#section-3.3.1 Envoy should reject
     918             :   // transfer-codings it does not understand.
     919             :   // Per https://tools.ietf.org/html/rfc7231#section-4.3.6 a payload with a
     920             :   // CONNECT request has no defined semantics, and may be rejected.
     921         639 :   if (request_or_response_headers.TransferEncoding()) {
     922         412 :     const absl::string_view encoding = request_or_response_headers.getTransferEncodingValue();
     923         412 :     if (!absl::EqualsIgnoreCase(encoding, header_values.TransferEncodingValues.Chunked) ||
     924         412 :         parser_->methodName() == header_values.MethodValues.Connect) {
     925          47 :       error_code_ = Http::Code::NotImplemented;
     926          47 :       RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidTransferEncoding));
     927          47 :       return codecProtocolError("http/1.1 protocol error: unsupported transfer encoding");
     928          47 :     }
     929         412 :   }
     930         592 : #endif
     931             : 
     932         592 :   auto statusor = onHeadersCompleteBase();
     933         592 :   if (!statusor.ok()) {
     934          56 :     RETURN_IF_ERROR(statusor.status());
     935          56 :   }
     936             : 
     937         536 :   header_parsing_state_ = HeaderParsingState::Done;
     938             : 
     939             :   // Returning CallbackResult::NoBodyData informs http_parser to not expect a body or further data
     940             :   // on this connection.
     941         536 :   return handling_upgrade_ ? CallbackResult::NoBodyData : statusor.value();
     942         592 : }
     943             : 
     944         395 : StatusOr<CallbackResult> ConnectionImpl::onMessageCompleteImpl() {
     945         395 :   ENVOY_CONN_LOG(trace, "message complete", connection_);
     946             : 
     947         395 :   dispatchBufferedBody();
     948             : 
     949         395 :   if (handling_upgrade_) {
     950             :     // If this is an upgrade request, swallow the onMessageComplete. The
     951             :     // upgrade payload will be treated as stream body.
     952           2 :     ASSERT(!deferred_end_stream_headers_);
     953           2 :     ENVOY_CONN_LOG(trace, "Pausing parser due to upgrade.", connection_);
     954           2 :     return parser_->pause();
     955           2 :   }
     956             : 
     957             :   // If true, this indicates we were processing trailers and must
     958             :   // move the last header into current_header_map_
     959         393 :   if (header_parsing_state_ == HeaderParsingState::Value) {
     960           0 :     RETURN_IF_ERROR(completeCurrentHeader());
     961           0 :   }
     962             : 
     963         393 :   return onMessageCompleteBase();
     964         393 : }
     965             : 
     966        1354 : void ConnectionImpl::dispatchBufferedBody() {
     967        1354 :   ASSERT(parser_->getStatus() == ParserStatus::Ok || parser_->getStatus() == ParserStatus::Paused);
     968        1354 :   ASSERT(codec_status_.ok());
     969        1354 :   if (buffered_body_.length() > 0) {
     970         265 :     onBody(buffered_body_);
     971         265 :     buffered_body_.drain(buffered_body_.length());
     972         265 :   }
     973        1354 : }
     974             : 
     975         247 : void ConnectionImpl::onResetStreamBase(StreamResetReason reason) {
     976         247 :   ASSERT(!reset_stream_called_);
     977         247 :   reset_stream_called_ = true;
     978         247 :   onResetStream(reason);
     979         247 : }
     980             : 
     981           0 : void ConnectionImpl::dumpState(std::ostream& os, int indent_level) const {
     982           0 :   const char* spaces = spacesForLevel(indent_level);
     983           0 :   os << spaces << "Http1::ConnectionImpl " << this << DUMP_MEMBER(dispatching_)
     984           0 :      << DUMP_MEMBER(dispatching_slice_already_drained_) << DUMP_MEMBER(reset_stream_called_)
     985           0 :      << DUMP_MEMBER(handling_upgrade_) << DUMP_MEMBER(deferred_end_stream_headers_)
     986           0 :      << DUMP_MEMBER(processing_trailers_) << DUMP_MEMBER(buffered_body_.length());
     987             : 
     988             :   // Dump header parsing state, and any progress on headers.
     989           0 :   os << DUMP_MEMBER(header_parsing_state_);
     990           0 :   os << DUMP_MEMBER_AS(current_header_field_, current_header_field_.getStringView());
     991           0 :   os << DUMP_MEMBER_AS(current_header_value_, current_header_value_.getStringView());
     992             : 
     993             :   // Dump Child
     994           0 :   os << '\n';
     995           0 :   dumpAdditionalState(os, indent_level);
     996             : 
     997             :   // Dump the first slice of the dispatching buffer if not drained escaping
     998             :   // certain characters. We do this last as the slice could be rather large.
     999           0 :   if (current_dispatching_buffer_ == nullptr || dispatching_slice_already_drained_) {
    1000             :     // Buffer is either null or already drained (in the body).
    1001             :     // Use the macro for consistent formatting.
    1002           0 :     os << DUMP_NULLABLE_MEMBER(current_dispatching_buffer_, "drained");
    1003           0 :     return;
    1004           0 :   } else {
    1005           0 :     absl::string_view front_slice = [](Buffer::RawSlice slice) {
    1006           0 :       return absl::string_view(static_cast<const char*>(slice.mem_), slice.len_);
    1007           0 :     }(current_dispatching_buffer_->frontSlice());
    1008             : 
    1009             :     // Dump buffer data escaping \r, \n, \t, ", ', and \.
    1010             :     // This is not the most performant implementation, but we're crashing and
    1011             :     // cannot allocate memory.
    1012           0 :     os << spaces << "current_dispatching_buffer_ front_slice length: " << front_slice.length()
    1013           0 :        << " contents: \"";
    1014           0 :     StringUtil::escapeToOstream(os, front_slice);
    1015           0 :     os << "\"\n";
    1016           0 :   }
    1017           0 : }
    1018             : 
    1019           0 : void ServerConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const {
    1020           0 :   const char* spaces = spacesForLevel(indent_level);
    1021             : 
    1022           0 :   DUMP_DETAILS(active_request_);
    1023           0 :   os << '\n';
    1024             : 
    1025             :   // Dump header map, it may be null if it was moved to the request, and
    1026             :   // request_url.
    1027           0 :   if (absl::holds_alternative<RequestHeaderMapPtr>(headers_or_trailers_)) {
    1028           0 :     DUMP_DETAILS(absl::get<RequestHeaderMapPtr>(headers_or_trailers_));
    1029           0 :   } else {
    1030           0 :     DUMP_DETAILS(absl::get<RequestTrailerMapPtr>(headers_or_trailers_));
    1031           0 :   }
    1032           0 : }
    1033             : 
    1034           0 : void ClientConnectionImpl::dumpAdditionalState(std::ostream& os, int indent_level) const {
    1035           0 :   const char* spaces = spacesForLevel(indent_level);
    1036             :   // Dump header map, it may be null if it was moved to the request.
    1037           0 :   if (absl::holds_alternative<ResponseHeaderMapPtr>(headers_or_trailers_)) {
    1038           0 :     DUMP_DETAILS(absl::get<ResponseHeaderMapPtr>(headers_or_trailers_));
    1039           0 :   } else {
    1040           0 :     DUMP_DETAILS(absl::get<ResponseTrailerMapPtr>(headers_or_trailers_));
    1041           0 :   }
    1042             : 
    1043             :   // Dump the associated request.
    1044           0 :   os << spaces << "Dumping corresponding downstream request:";
    1045           0 :   if (pending_response_.has_value()) {
    1046           0 :     os << '\n';
    1047           0 :     const ResponseDecoder* decoder = pending_response_.value().decoder_;
    1048           0 :     DUMP_DETAILS(decoder);
    1049           0 :   } else {
    1050           0 :     os << " null\n";
    1051           0 :   }
    1052           0 : }
    1053             : 
    1054             : ServerConnectionImpl::ServerConnectionImpl(
    1055             :     Network::Connection& connection, CodecStats& stats, ServerConnectionCallbacks& callbacks,
    1056             :     const Http1Settings& settings, uint32_t max_request_headers_kb,
    1057             :     const uint32_t max_request_headers_count,
    1058             :     envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
    1059             :         headers_with_underscores_action,
    1060             :     Server::OverloadManager& overload_manager)
    1061             :     : ConnectionImpl(connection, stats, settings, MessageType::Request, max_request_headers_kb,
    1062             :                      max_request_headers_count),
    1063             :       callbacks_(callbacks),
    1064         367 :       response_buffer_releasor_([this](const Buffer::OwnedBufferFragmentImpl* fragment) {
    1065         367 :         releaseOutboundResponse(fragment);
    1066         367 :       }),
    1067             :       owned_output_buffer_(connection.dispatcher().getWatermarkFactory().createBuffer(
    1068           0 :           [&]() -> void { this->onBelowLowWatermark(); },
    1069           0 :           [&]() -> void { this->onAboveHighWatermark(); },
    1070           0 :           []() -> void { /* TODO(adisuissa): handle overflow watermark */ })),
    1071             :       headers_with_underscores_action_(headers_with_underscores_action),
    1072             :       abort_dispatch_(
    1073        1670 :           overload_manager.getLoadShedPoint("envoy.load_shed_points.http1_server_abort_dispatch")) {
    1074        1670 :   ENVOY_LOG_ONCE_IF(trace, abort_dispatch_ == nullptr,
    1075        1670 :                     "LoadShedPoint envoy.load_shed_points.http1_server_abort_dispatch is not "
    1076        1670 :                     "found. Is it configured?");
    1077        1670 :   owned_output_buffer_->setWatermarks(connection.bufferLimit());
    1078             :   // Inform parent
    1079        1670 :   output_buffer_ = owned_output_buffer_.get();
    1080        1670 : }
    1081             : 
    1082        4959 : uint32_t ServerConnectionImpl::getHeadersSize() {
    1083             :   // Add in the size of the request URL if processing request headers.
    1084        4959 :   const uint32_t url_size =
    1085        4959 :       (!processing_trailers_ && active_request_) ? active_request_->request_url_.size() : 0;
    1086        4959 :   return url_size + ConnectionImpl::getHeadersSize();
    1087        4959 : }
    1088             : 
    1089         367 : void ServerConnectionImpl::onEncodeComplete() {
    1090         367 :   if (active_request_->remote_complete_) {
    1091             :     // Only do this if remote is complete. If we are replying before the request is complete the
    1092             :     // only logical thing to do is for higher level code to reset() / close the connection so we
    1093             :     // leave the request around so that it can fire reset callbacks.
    1094         155 :     connection_.dispatcher().deferredDelete(std::move(active_request_));
    1095         155 :   }
    1096         367 : }
    1097             : 
    1098         436 : Status ServerConnectionImpl::handlePath(RequestHeaderMap& headers, absl::string_view method) {
    1099         436 :   const Http::HeaderValues& header_values = Http::Headers::get();
    1100         436 :   HeaderString path(header_values.Path);
    1101             : 
    1102         436 :   bool is_connect = (method == header_values.MethodValues.Connect);
    1103             : 
    1104             :   // The url is relative or a wildcard when the method is OPTIONS. Nothing to do here.
    1105         436 :   if (!is_connect && !active_request_->request_url_.getStringView().empty() &&
    1106         436 :       (active_request_->request_url_.getStringView()[0] == '/' ||
    1107         409 :        (method == header_values.MethodValues.Options &&
    1108         402 :         active_request_->request_url_.getStringView()[0] == '*'))) {
    1109         402 :     headers.addViaMove(std::move(path), std::move(active_request_->request_url_));
    1110         402 :     return okStatus();
    1111         402 :   }
    1112             : 
    1113             :   // If absolute_urls and/or connect are not going be handled, copy the url and return.
    1114             :   // This forces the behavior to be backwards compatible with the old codec behavior.
    1115             :   // CONNECT "urls" are actually host:port so look like absolute URLs to the above checks.
    1116             :   // Absolute URLS in CONNECT requests will be rejected below by the URL class validation.
    1117             : 
    1118             :   /**
    1119             :    * @param scheme the scheme to validate
    1120             :    * @return bool true if the scheme is http.
    1121             :    */
    1122          34 :   if (!codec_settings_.allow_absolute_url_ && !is_connect) {
    1123           5 :     headers.addViaMove(std::move(path), std::move(active_request_->request_url_));
    1124           5 :     return okStatus();
    1125           5 :   }
    1126             : 
    1127          29 :   Utility::Url absolute_url;
    1128          29 :   if (!absolute_url.initialize(active_request_->request_url_.getStringView(), is_connect)) {
    1129          28 :     RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidUrl));
    1130          28 :     return codecProtocolError("http/1.1 protocol error: invalid url in request line");
    1131          28 :   }
    1132             :   // RFC7230#5.7
    1133             :   // When a proxy receives a request with an absolute-form of
    1134             :   // request-target, the proxy MUST ignore the received Host header field
    1135             :   // (if any) and instead replace it with the host information of the
    1136             :   // request-target. A proxy that forwards such a request MUST generate a
    1137             :   // new Host field-value based on the received request-target rather than
    1138             :   // forward the received Host field-value.
    1139           1 :   headers.setHost(absolute_url.hostAndPort());
    1140             :   // Add the scheme and validate to ensure no https://
    1141             :   // requests are accepted over unencrypted connections by front-line Envoys.
    1142           1 :   if (!is_connect) {
    1143           1 :     if (Runtime::runtimeFeatureEnabled(
    1144           1 :             "envoy.reloadable_features.allow_absolute_url_with_mixed_scheme")) {
    1145           1 :       headers.setScheme(absl::AsciiStrToLower(absolute_url.scheme()));
    1146           1 :     } else {
    1147           0 :       headers.setScheme(absolute_url.scheme());
    1148           0 :     }
    1149           1 :     if (!Utility::schemeIsValid(headers.getSchemeValue())) {
    1150           0 :       RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidScheme));
    1151           0 :       return codecProtocolError("http/1.1 protocol error: invalid scheme");
    1152           0 :     }
    1153           1 :     if (codec_settings_.validate_scheme_ && Utility::schemeIsHttps(absolute_url.scheme()) &&
    1154           1 :         !connection().ssl()) {
    1155           0 :       error_code_ = Http::Code::Forbidden;
    1156           0 :       RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().HttpsInPlaintext));
    1157           0 :       return codecProtocolError("http/1.1 protocol error: https in the clear");
    1158           0 :     }
    1159           1 :   }
    1160             : 
    1161           1 :   if (!absolute_url.pathAndQueryParams().empty()) {
    1162           1 :     headers.setPath(absolute_url.pathAndQueryParams());
    1163           1 :   }
    1164           1 :   active_request_->request_url_.clear();
    1165           1 :   return okStatus();
    1166           1 : }
    1167             : 
    1168         408 : Status ServerConnectionImpl::checkProtocolVersion(RequestHeaderMap& headers) {
    1169         408 :   if (protocol() == Protocol::Http10) {
    1170             :     // Assume this is HTTP/1.0. This is fine for HTTP/0.9 but this code will also affect any
    1171             :     // requests with non-standard version numbers (0.9, 1.3), basically anything which is not
    1172             :     // HTTP/1.1.
    1173             :     //
    1174             :     // The protocol may have shifted in the HTTP/1.0 case so reset it.
    1175          44 :     if (!codec_settings_.accept_http_10_) {
    1176             :       // Send "Upgrade Required" if HTTP/1.0 support is not explicitly configured on.
    1177          19 :       error_code_ = Http::Code::UpgradeRequired;
    1178          19 :       RETURN_IF_ERROR(sendProtocolError(StreamInfo::ResponseCodeDetails::get().LowVersion));
    1179          19 :       return codecProtocolError("Upgrade required for HTTP/1.0 or HTTP/0.9");
    1180          19 :     }
    1181          25 :     if (!headers.Host() && !codec_settings_.default_host_for_http_10_.empty()) {
    1182             :       // Add a default host if configured to do so.
    1183          24 :       headers.setHost(codec_settings_.default_host_for_http_10_);
    1184          24 :     }
    1185          25 :   }
    1186         389 :   return okStatus();
    1187         408 : }
    1188             : 
    1189         436 : Envoy::StatusOr<CallbackResult> ServerConnectionImpl::onHeadersCompleteBase() {
    1190             :   // Handle the case where response happens prior to request complete. It's up to upper layer code
    1191             :   // to disconnect the connection but we shouldn't fire any more events since it doesn't make
    1192             :   // sense.
    1193         436 :   if (active_request_) {
    1194         436 :     auto& headers = absl::get<RequestHeaderMapPtr>(headers_or_trailers_);
    1195         436 :     ENVOY_CONN_LOG(trace, "Server: onHeadersComplete size={}", connection_, headers->size());
    1196             : 
    1197         436 :     if (!handling_upgrade_ && headers->Connection()) {
    1198             :       // If we fail to sanitize the request, return a 400 to the client
    1199           2 :       if (!Utility::sanitizeConnectionHeader(*headers)) {
    1200           0 :         absl::string_view header_value = headers->getConnectionValue();
    1201           0 :         ENVOY_CONN_LOG(debug, "Invalid nominated headers in Connection: {}", connection_,
    1202           0 :                        header_value);
    1203           0 :         error_code_ = Http::Code::BadRequest;
    1204           0 :         RETURN_IF_ERROR(
    1205           0 :             sendProtocolError(Http1ResponseCodeDetails::get().ConnectionHeaderSanitization));
    1206           0 :         return codecProtocolError("Invalid nominated headers in Connection.");
    1207           0 :       }
    1208           2 :     }
    1209             : 
    1210             :     // Inform the response encoder about any HEAD method, so it can set content
    1211             :     // length and transfer encoding headers correctly.
    1212         436 :     const Http::HeaderValues& header_values = Http::Headers::get();
    1213         436 :     active_request_->response_encoder_.setIsResponseToHeadRequest(parser_->methodName() ==
    1214         436 :                                                                   header_values.MethodValues.Head);
    1215         436 :     active_request_->response_encoder_.setIsResponseToConnectRequest(
    1216         436 :         parser_->methodName() == header_values.MethodValues.Connect);
    1217             : 
    1218         436 :     RETURN_IF_ERROR(handlePath(*headers, parser_->methodName()));
    1219         408 :     ASSERT(active_request_->request_url_.empty());
    1220             : 
    1221         408 :     headers->setMethod(parser_->methodName());
    1222         408 :     RETURN_IF_ERROR(checkProtocolVersion(*headers));
    1223             : 
    1224             :     // Make sure the host is valid.
    1225         389 :     auto details = HeaderUtility::requestHeadersValid(*headers);
    1226         389 :     if (details.has_value()) {
    1227           1 :       RETURN_IF_ERROR(sendProtocolError(details.value().get()));
    1228           1 :       return codecProtocolError(
    1229           1 :           "http/1.1 protocol error: request headers failed spec compliance checks");
    1230           1 :     }
    1231             : 
    1232             :     // Determine here whether we have a body or not. This uses the new RFC semantics where the
    1233             :     // presence of content-length or chunked transfer-encoding indicates a body vs. a particular
    1234             :     // method. If there is no body, we defer raising decodeHeaders() until the parser is flushed
    1235             :     // with message complete. This allows upper layers to behave like HTTP/2 and prevents a proxy
    1236             :     // scenario where the higher layers stream through and implicitly switch to chunked transfer
    1237             :     // encoding because end stream with zero body length has not yet been indicated.
    1238         388 :     if (parser_->isChunked() ||
    1239         388 :         (parser_->contentLength().has_value() && parser_->contentLength().value() > 0) ||
    1240         388 :         handling_upgrade_) {
    1241         232 :       active_request_->request_decoder_->decodeHeaders(std::move(headers), false);
    1242             : 
    1243             :       // If the connection has been closed (or is closing) after decoding headers, pause the parser
    1244             :       // so we return control to the caller.
    1245         232 :       if (connection_.state() != Network::Connection::State::Open) {
    1246         117 :         return parser_->pause();
    1247         117 :       }
    1248         343 :     } else {
    1249         156 :       deferred_end_stream_headers_ = true;
    1250         156 :     }
    1251         388 :   }
    1252             : 
    1253         271 :   return CallbackResult::Success;
    1254         436 : }
    1255             : 
    1256        1642 : Status ServerConnectionImpl::onMessageBeginBase() {
    1257        1642 :   if (!resetStreamCalled()) {
    1258        1642 :     ASSERT(active_request_ == nullptr);
    1259        1642 :     active_request_ = std::make_unique<ActiveRequest>(*this, std::move(bytes_meter_before_stream_));
    1260        1642 :     active_request_->request_decoder_ = &callbacks_.newStream(active_request_->response_encoder_);
    1261             : 
    1262             :     // Check for pipelined request flood as we prepare to accept a new request.
    1263             :     // Parse errors that happen prior to onMessageBegin result in stream termination, it is not
    1264             :     // possible to overflow output buffers with early parse errors.
    1265        1642 :     RETURN_IF_ERROR(doFloodProtectionChecks());
    1266        1642 :   }
    1267        1642 :   return okStatus();
    1268        1642 : }
    1269             : 
    1270        1032 : Status ServerConnectionImpl::onUrlBase(const char* data, size_t length) {
    1271        1032 :   if (active_request_) {
    1272        1032 :     active_request_->request_url_.append(data, length);
    1273             : 
    1274        1032 :     RETURN_IF_ERROR(checkMaxHeadersSize());
    1275        1032 :   }
    1276             : 
    1277        1032 :   return okStatus();
    1278        1032 : }
    1279             : 
    1280         129 : void ServerConnectionImpl::onBody(Buffer::Instance& data) {
    1281         129 :   ASSERT(!deferred_end_stream_headers_);
    1282         129 :   if (active_request_) {
    1283         129 :     ENVOY_CONN_LOG(trace, "body size={}", connection_, data.length());
    1284         129 :     active_request_->request_decoder_->decodeData(data, false);
    1285         129 :   }
    1286         129 : }
    1287             : 
    1288        1729 : Http::Status ServerConnectionImpl::dispatch(Buffer::Instance& data) {
    1289        1729 :   if (abort_dispatch_ != nullptr && abort_dispatch_->shouldShedLoad()) {
    1290           0 :     RETURN_IF_ERROR(sendOverloadError());
    1291           0 :     return envoyOverloadError("Aborting Server Dispatch");
    1292           0 :   }
    1293             : 
    1294        1729 :   if (active_request_ != nullptr && active_request_->remote_complete_) {
    1295             :     // Eagerly read disable the connection if the downstream is sending pipelined requests as we
    1296             :     // serially process them. Reading from the connection will be re-enabled after the active
    1297             :     // request is completed.
    1298           1 :     active_request_->response_encoder_.readDisable(true);
    1299           1 :     return okStatus();
    1300           1 :   }
    1301             : 
    1302        1728 :   Http::Status status = ConnectionImpl::dispatch(data);
    1303             : 
    1304        1728 :   if (active_request_ != nullptr && active_request_->remote_complete_) {
    1305             :     // Read disable the connection if the downstream is sending additional data while we are working
    1306             :     // on an existing request. Reading from the connection will be re-enabled after the active
    1307             :     // request is completed.
    1308         130 :     if (data.length() > 0) {
    1309          62 :       active_request_->response_encoder_.readDisable(true);
    1310          62 :     }
    1311         130 :   }
    1312        1728 :   return status;
    1313        1729 : }
    1314             : 
    1315         247 : CallbackResult ServerConnectionImpl::onMessageCompleteBase() {
    1316         247 :   ASSERT(!handling_upgrade_);
    1317         247 :   if (active_request_) {
    1318             : 
    1319             :     // The request_decoder should be non-null after we've called the newStream on callbacks.
    1320         247 :     ASSERT(active_request_->request_decoder_);
    1321         247 :     active_request_->remote_complete_ = true;
    1322             : 
    1323         247 :     if (deferred_end_stream_headers_) {
    1324         156 :       active_request_->request_decoder_->decodeHeaders(
    1325         156 :           std::move(absl::get<RequestHeaderMapPtr>(headers_or_trailers_)), true);
    1326         156 :       deferred_end_stream_headers_ = false;
    1327         220 :     } else if (processing_trailers_) {
    1328           0 :       active_request_->request_decoder_->decodeTrailers(
    1329           0 :           std::move(absl::get<RequestTrailerMapPtr>(headers_or_trailers_)));
    1330          91 :     } else {
    1331          91 :       Buffer::OwnedImpl buffer;
    1332          91 :       active_request_->request_decoder_->decodeData(buffer, true);
    1333          91 :     }
    1334             : 
    1335             :     // Reset to ensure no information from one requests persists to the next.
    1336         247 :     headers_or_trailers_.emplace<RequestHeaderMapPtr>(nullptr);
    1337         247 :   }
    1338             : 
    1339             :   // Always pause the parser so that the calling code can process 1 request at a time and apply
    1340             :   // back pressure. However this means that the calling code needs to detect if there is more data
    1341             :   // in the buffer and dispatch it again.
    1342         247 :   return parser_->pause();
    1343         247 : }
    1344             : 
    1345         215 : void ServerConnectionImpl::onResetStream(StreamResetReason reason) {
    1346         215 :   if (active_request_) {
    1347         213 :     active_request_->response_encoder_.runResetCallbacks(reason);
    1348         213 :     connection_.dispatcher().deferredDelete(std::move(active_request_));
    1349         213 :   }
    1350         215 : }
    1351             : 
    1352           0 : Status ServerConnectionImpl::sendOverloadError() {
    1353           0 :   const bool latched_dispatching = dispatching_;
    1354             : 
    1355             :   // The codec might be in the early stages of server dispatching where this isn't yet
    1356             :   // flipped to true.
    1357           0 :   dispatching_ = true;
    1358           0 :   error_code_ = Http::Code::InternalServerError;
    1359           0 :   auto status = sendProtocolError(Envoy::StreamInfo::ResponseCodeDetails::get().Overload);
    1360           0 :   dispatching_ = latched_dispatching;
    1361           0 :   return status;
    1362           0 : }
    1363             : 
    1364        1116 : Status ServerConnectionImpl::sendProtocolError(absl::string_view details) {
    1365             :   // We do this here because we may get a protocol error before we have a logical stream.
    1366        1116 :   if (active_request_ == nullptr) {
    1367         179 :     RETURN_IF_ERROR(onMessageBeginImpl());
    1368         179 :   }
    1369        1116 :   ASSERT(active_request_);
    1370             : 
    1371        1116 :   active_request_->response_encoder_.setDetails(details);
    1372        1116 :   if (!active_request_->response_encoder_.startedResponse()) {
    1373        1116 :     active_request_->request_decoder_->sendLocalReply(
    1374        1116 :         error_code_, CodeUtility::toString(error_code_), nullptr, absl::nullopt, details);
    1375        1116 :   }
    1376        1116 :   return okStatus();
    1377        1116 : }
    1378             : 
    1379           0 : void ServerConnectionImpl::onAboveHighWatermark() {
    1380           0 :   if (active_request_) {
    1381           0 :     active_request_->response_encoder_.runHighWatermarkCallbacks();
    1382           0 :   }
    1383           0 : }
    1384           0 : void ServerConnectionImpl::onBelowLowWatermark() {
    1385           0 :   if (active_request_) {
    1386           0 :     active_request_->response_encoder_.runLowWatermarkCallbacks();
    1387           0 :   }
    1388           0 : }
    1389             : 
    1390             : void ServerConnectionImpl::releaseOutboundResponse(
    1391         367 :     const Buffer::OwnedBufferFragmentImpl* fragment) {
    1392         367 :   ASSERT(outbound_responses_ >= 1);
    1393         367 :   --outbound_responses_;
    1394         367 :   delete fragment;
    1395         367 : }
    1396             : 
    1397        1832 : Status ServerConnectionImpl::checkHeaderNameForUnderscores() {
    1398        1832 : #ifndef ENVOY_ENABLE_UHV
    1399             :   // This check has been moved to UHV
    1400        1832 :   if (headers_with_underscores_action_ != envoy::config::core::v3::HttpProtocolOptions::ALLOW &&
    1401        1832 :       Http::HeaderUtility::headerNameContainsUnderscore(current_header_field_.getStringView())) {
    1402           0 :     if (headers_with_underscores_action_ ==
    1403           0 :         envoy::config::core::v3::HttpProtocolOptions::DROP_HEADER) {
    1404           0 :       ENVOY_CONN_LOG(debug, "Dropping header with invalid characters in its name: {}", connection_,
    1405           0 :                      current_header_field_.getStringView());
    1406           0 :       stats_.incDroppedHeadersWithUnderscores();
    1407           0 :       current_header_field_.clear();
    1408           0 :       current_header_value_.clear();
    1409           0 :     } else {
    1410           0 :       ENVOY_CONN_LOG(debug, "Rejecting request due to header name with underscores: {}",
    1411           0 :                      connection_, current_header_field_.getStringView());
    1412           0 :       error_code_ = Http::Code::BadRequest;
    1413           0 :       RETURN_IF_ERROR(sendProtocolError(Http1ResponseCodeDetails::get().InvalidUnderscore));
    1414           0 :       stats_.incRequestsRejectedWithUnderscoresInHeaders();
    1415           0 :       return codecProtocolError("http/1.1 protocol error: header name contains underscores");
    1416           0 :     }
    1417           0 :   }
    1418             : #else
    1419             :   // Workaround for gcc not understanding [[maybe_unused]] for class members.
    1420             :   (void)headers_with_underscores_action_;
    1421             : #endif
    1422        1832 :   return okStatus();
    1423        1832 : }
    1424             : 
    1425           0 : void ServerConnectionImpl::ActiveRequest::dumpState(std::ostream& os, int indent_level) const {
    1426           0 :   (void)indent_level;
    1427           0 :   os << DUMP_MEMBER_AS(
    1428           0 :       request_url_, !request_url_.getStringView().empty() ? request_url_.getStringView() : "null");
    1429           0 :   os << DUMP_MEMBER(response_encoder_.local_end_stream_);
    1430           0 : }
    1431             : 
    1432             : ClientConnectionImpl::ClientConnectionImpl(Network::Connection& connection, CodecStats& stats,
    1433             :                                            ConnectionCallbacks&, const Http1Settings& settings,
    1434             :                                            const uint32_t max_response_headers_count,
    1435             :                                            bool passing_through_proxy)
    1436             :     : ConnectionImpl(connection, stats, settings, MessageType::Response, MAX_RESPONSE_HEADERS_KB,
    1437             :                      max_response_headers_count),
    1438             :       owned_output_buffer_(connection.dispatcher().getWatermarkFactory().createBuffer(
    1439           0 :           [&]() -> void { this->onBelowLowWatermark(); },
    1440           0 :           [&]() -> void { this->onAboveHighWatermark(); },
    1441           0 :           []() -> void { /* TODO(adisuissa): handle overflow watermark */ })),
    1442        1442 :       passing_through_proxy_(passing_through_proxy) {
    1443        1442 :   owned_output_buffer_->setWatermarks(connection.bufferLimit());
    1444             :   // Inform parent
    1445        1442 :   output_buffer_ = owned_output_buffer_.get();
    1446        1442 : }
    1447             : 
    1448         291 : bool ClientConnectionImpl::cannotHaveBody() {
    1449         291 :   if (pending_response_.has_value() && pending_response_.value().encoder_.headRequest()) {
    1450           2 :     ASSERT(!pending_response_done_);
    1451           2 :     return true;
    1452         289 :   } else if (parser_->statusCode() == Http::Code::NoContent ||
    1453         289 :              parser_->statusCode() == Http::Code::NotModified ||
    1454         289 :              (parser_->statusCode() >= Http::Code::OK &&
    1455         283 :               (parser_->contentLength().has_value() && parser_->contentLength().value() == 0) &&
    1456         283 :               !parser_->isChunked())) {
    1457          14 :     return true;
    1458         276 :   } else {
    1459         275 :     return false;
    1460         275 :   }
    1461         291 : }
    1462             : 
    1463         220 : RequestEncoder& ClientConnectionImpl::newStream(ResponseDecoder& response_decoder) {
    1464             :   // If reads were disabled due to flow control, we expect reads to always be enabled again before
    1465             :   // reusing this connection. This is done when the response is received.
    1466         220 :   ASSERT(connection_.readEnabled());
    1467             : 
    1468         220 :   ASSERT(!pending_response_.has_value());
    1469         220 :   ASSERT(pending_response_done_);
    1470         220 :   pending_response_.emplace(*this, std::move(bytes_meter_before_stream_), &response_decoder);
    1471         220 :   pending_response_done_ = false;
    1472         220 :   return pending_response_.value().encoder_;
    1473         220 : }
    1474             : 
    1475         156 : Status ClientConnectionImpl::onStatusBase(const char* data, size_t length) {
    1476         156 :   auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
    1477         156 :   StatefulHeaderKeyFormatterOptRef formatter(headers->formatter());
    1478         156 :   if (formatter.has_value()) {
    1479           0 :     formatter->setReasonPhrase(absl::string_view(data, length));
    1480           0 :   }
    1481             : 
    1482         156 :   return okStatus();
    1483         156 : }
    1484             : 
    1485         156 : Envoy::StatusOr<CallbackResult> ClientConnectionImpl::onHeadersCompleteBase() {
    1486         156 :   ENVOY_CONN_LOG(trace, "status_code {}", connection_, enumToInt(parser_->statusCode()));
    1487             : 
    1488             :   // Handle the case where the client is closing a kept alive connection (by sending a 408
    1489             :   // with a 'Connection: close' header). In this case we just let response flush out followed
    1490             :   // by the remote close.
    1491         156 :   if (!pending_response_.has_value() && !resetStreamCalled()) {
    1492           8 :     return prematureResponseError("", parser_->statusCode());
    1493         148 :   } else if (pending_response_.has_value()) {
    1494         148 :     ASSERT(!pending_response_done_);
    1495         148 :     auto& headers = absl::get<ResponseHeaderMapPtr>(headers_or_trailers_);
    1496         148 :     ENVOY_CONN_LOG(trace, "Client: onHeadersComplete size={}", connection_, headers->size());
    1497         148 :     headers->setStatus(enumToInt(parser_->statusCode()));
    1498             : 
    1499         148 :     if (parser_->statusCode() >= Http::Code::OK &&
    1500         148 :         parser_->statusCode() < Http::Code::MultipleChoices &&
    1501         148 :         pending_response_.value().encoder_.connectRequest()) {
    1502           0 :       ENVOY_CONN_LOG(trace, "codec entering upgrade mode for CONNECT response.", connection_);
    1503           0 :       handling_upgrade_ = true;
    1504           0 :     }
    1505             : 
    1506         148 :     if (parser_->statusCode() < Http::Code::OK || parser_->statusCode() == Http::Code::NoContent) {
    1507           8 :       if (headers->TransferEncoding()) {
    1508           0 :         RETURN_IF_ERROR(
    1509           0 :             sendProtocolError(Http1ResponseCodeDetails::get().TransferEncodingNotAllowed));
    1510           0 :         return codecProtocolError(
    1511           0 :             "http/1.1 protocol error: transfer encoding not allowed in 1xx or 204");
    1512           0 :       }
    1513             : 
    1514           8 :       if (headers->ContentLength()) {
    1515             :         // Report a protocol error for non-zero Content-Length, but paper over zero Content-Length.
    1516           0 :         if (headers->ContentLength()->value().getStringView() != "0") {
    1517           0 :           RETURN_IF_ERROR(
    1518           0 :               sendProtocolError(Http1ResponseCodeDetails::get().ContentLengthNotAllowed));
    1519           0 :           return codecProtocolError(
    1520           0 :               "http/1.1 protocol error: content length not allowed in 1xx or 204");
    1521           0 :         }
    1522             : 
    1523           0 :         headers->removeContentLength();
    1524           0 :       }
    1525           8 :     }
    1526             : 
    1527         148 :     if (HeaderUtility::isSpecial1xx(*headers)) {
    1528           5 :       pending_response_.value().decoder_->decode1xxHeaders(std::move(headers));
    1529         143 :     } else if (cannotHaveBody() && !handling_upgrade_) {
    1530           8 :       deferred_end_stream_headers_ = true;
    1531         139 :     } else {
    1532         135 :       pending_response_.value().decoder_->decodeHeaders(std::move(headers), false);
    1533         135 :     }
    1534             : 
    1535             :     // http-parser treats 1xx headers as their own complete response. Swallow the spurious
    1536             :     // onMessageComplete and continue processing for purely informational headers.
    1537             :     // 101-SwitchingProtocols is exempt as all data after the header is proxied through after
    1538             :     // upgrading.
    1539         148 :     if (CodeUtility::is1xx(enumToInt(parser_->statusCode())) &&
    1540         148 :         parser_->statusCode() != Http::Code::SwitchingProtocols) {
    1541           5 :       ignore_message_complete_for_1xx_ = true;
    1542             :       // Reset to ensure no information from the 1xx headers is used for the response headers.
    1543           5 :       headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
    1544           5 :     }
    1545         148 :   }
    1546             : 
    1547             :   // Here we deal with cases where the response cannot have a body by returning
    1548             :   // CallbackResult::NoBody, but http_parser does not deal with it for us.
    1549         148 :   return cannotHaveBody() ? CallbackResult::NoBody : CallbackResult::Success;
    1550         156 : }
    1551             : 
    1552           1 : bool ClientConnectionImpl::upgradeAllowed() const {
    1553           1 :   if (pending_response_.has_value()) {
    1554           1 :     return pending_response_->encoder_.upgradeRequest();
    1555           1 :   }
    1556           0 :   return false;
    1557           1 : }
    1558             : 
    1559         140 : void ClientConnectionImpl::onBody(Buffer::Instance& data) {
    1560         140 :   ASSERT(!deferred_end_stream_headers_);
    1561         140 :   if (pending_response_.has_value()) {
    1562         140 :     ASSERT(!pending_response_done_);
    1563         140 :     pending_response_.value().decoder_->decodeData(data, false);
    1564         140 :   }
    1565         140 : }
    1566             : 
    1567         146 : CallbackResult ClientConnectionImpl::onMessageCompleteBase() {
    1568         146 :   ENVOY_CONN_LOG(trace, "message complete", connection_);
    1569         146 :   if (ignore_message_complete_for_1xx_) {
    1570           5 :     ignore_message_complete_for_1xx_ = false;
    1571           5 :     return CallbackResult::Success;
    1572           5 :   }
    1573         141 :   if (pending_response_.has_value()) {
    1574         141 :     ASSERT(!pending_response_done_);
    1575             :     // After calling decodeData() with end stream set to true, we should no longer be able to reset.
    1576         141 :     PendingResponse& response = pending_response_.value();
    1577             :     // Encoder is used as part of decode* calls later in this function so pending_response_ can not
    1578             :     // be reset just yet. Preserve the state in pending_response_done_ instead.
    1579         141 :     pending_response_done_ = true;
    1580             : 
    1581         141 :     if (deferred_end_stream_headers_) {
    1582           8 :       response.decoder_->decodeHeaders(
    1583           8 :           std::move(absl::get<ResponseHeaderMapPtr>(headers_or_trailers_)), true);
    1584           8 :       deferred_end_stream_headers_ = false;
    1585         139 :     } else if (processing_trailers_) {
    1586           0 :       response.decoder_->decodeTrailers(
    1587           0 :           std::move(absl::get<ResponseTrailerMapPtr>(headers_or_trailers_)));
    1588         133 :     } else {
    1589         133 :       Buffer::OwnedImpl buffer;
    1590         133 :       response.decoder_->decodeData(buffer, true);
    1591         133 :     }
    1592             : 
    1593             :     // Reset to ensure no information from one requests persists to the next.
    1594         141 :     pending_response_.reset();
    1595         141 :     headers_or_trailers_.emplace<ResponseHeaderMapPtr>(nullptr);
    1596         141 :   }
    1597             : 
    1598             :   // Pause the parser after a response is complete. Any remaining data indicates an error.
    1599         141 :   return parser_->pause();
    1600         146 : }
    1601             : 
    1602          32 : void ClientConnectionImpl::onResetStream(StreamResetReason reason) {
    1603             :   // Only raise reset if we did not already dispatch a complete response.
    1604          32 :   if (pending_response_.has_value() && !pending_response_done_) {
    1605          32 :     pending_response_.value().encoder_.runResetCallbacks(reason);
    1606          32 :     pending_response_done_ = true;
    1607          32 :     pending_response_.reset();
    1608          32 :   }
    1609          32 : }
    1610             : 
    1611        1088 : Status ClientConnectionImpl::sendProtocolError(absl::string_view details) {
    1612        1088 :   if (pending_response_.has_value()) {
    1613          14 :     ASSERT(!pending_response_done_);
    1614          14 :     pending_response_.value().encoder_.setDetails(details);
    1615          14 :   }
    1616        1088 :   return okStatus();
    1617        1088 : }
    1618             : 
    1619           0 : void ClientConnectionImpl::onAboveHighWatermark() {
    1620             :   // This should never happen without an active stream/request.
    1621           0 :   pending_response_.value().encoder_.runHighWatermarkCallbacks();
    1622           0 : }
    1623             : 
    1624           0 : void ClientConnectionImpl::onBelowLowWatermark() {
    1625             :   // This can get called without an active stream/request when the response completion causes us to
    1626             :   // close the connection, but in doing so go below low watermark.
    1627           0 :   if (pending_response_.has_value() && !pending_response_done_) {
    1628           0 :     pending_response_.value().encoder_.runLowWatermarkCallbacks();
    1629           0 :   }
    1630           0 : }
    1631             : 
    1632             : } // namespace Http1
    1633             : } // namespace Http
    1634             : } // namespace Envoy

Generated by: LCOV version 1.15