LCOV - code coverage report
Current view: top level - source/common/http/http1 - codec_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 112 166 67.5 %
Date: 2024-01-05 06:35:25 Functions: 52 71 73.2 %

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

Generated by: LCOV version 1.15