LCOV - code coverage report
Current view: top level - source/common/http/http2 - protocol_constraints.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 2 3 66.7 %
Date: 2024-01-05 06:35:25 Functions: 2 3 66.7 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <cstdint>
       4             : #include <functional>
       5             : 
       6             : #include "envoy/config/core/v3/protocol.pb.h"
       7             : #include "envoy/network/connection.h"
       8             : 
       9             : #include "source/common/http/http2/codec_stats.h"
      10             : #include "source/common/http/status.h"
      11             : 
      12             : #include "nghttp2/nghttp2.h"
      13             : 
      14             : namespace Envoy {
      15             : namespace Http {
      16             : namespace Http2 {
      17             : 
      18             : //  Class for detecting abusive peers and validating additional constraints imposed by Envoy.
      19             : //  This class does not check protocol compliance with the H/2 standard, as this is checked by
      20             : //  protocol framer/codec. Currently implemented constraints:
      21             : //  1. detection of control frame (i.e. PING) initiated floods.
      22             : //  2. detection of outbound DATA or HEADER frame floods.
      23             : //  4. zero length, PRIORITY and WINDOW_UPDATE floods.
      24             : 
      25             : class ProtocolConstraints : public ScopeTrackedObject {
      26             : public:
      27             :   using ReleasorProc = std::function<void()>;
      28             : 
      29             :   explicit ProtocolConstraints(CodecStats& stats,
      30             :                                const envoy::config::core::v3::Http2ProtocolOptions& http2_options);
      31             : 
      32             :   // Return ok status if no protocol constraints were violated.
      33             :   // Return error status of the first detected violation. Subsequent violations of constraints
      34             :   // do not reset the error status or increment stat counters.
      35           0 :   const Status& status() const { return status_; }
      36             : 
      37             :   // Increment counters of pending (buffered for sending to the peer) outbound frames.
      38             :   // If the `is_outbound_flood_monitored_control_frame` is false only the counter for all frame
      39             :   // types is incremented. If the `is_outbound_flood_monitored_control_frame` is true, both the
      40             :   // control frame and all frame types counters are incremented.
      41             :   // Returns callable for decrementing frame counters when frames was successfully written to
      42             :   // the underlying transport socket object.
      43             :   // To check if outbound frame constraints were violated call the `status()` method.
      44             :   // TODO(yanavlasov): return StatusOr<ReleasorProc> when flood checks are implemented for both
      45             :   // directions.
      46             :   ReleasorProc incrementOutboundFrameCount(bool is_outbound_flood_monitored_control_frame);
      47             : 
      48             :   // Track received frames of various types.
      49             :   // Return an error status if inbound frame constraints were violated.
      50             :   Status trackInboundFrames(size_t length, uint8_t type, uint8_t flags, uint32_t padding_length);
      51             :   // Increment the number of DATA frames sent to the peer.
      52       22334 :   void incrementOutboundDataFrameCount() { ++outbound_data_frames_; }
      53        1974 :   void incrementOpenedStreamCount() { ++opened_streams_; }
      54             : 
      55             :   Status checkOutboundFrameLimits();
      56             : 
      57             :   // ScopeTrackedObject
      58             :   void dumpState(std::ostream& os, int indent_level) const override;
      59             : 
      60             : private:
      61             :   void releaseOutboundFrame();
      62             :   void releaseOutboundControlFrame();
      63             :   Status checkInboundFrameLimits();
      64             : 
      65             :   Status status_;
      66             :   CodecStats& stats_;
      67             :   // This counter keeps track of the number of outbound frames of all types (these that were
      68             :   // buffered in the underlying connection but not yet written into the socket). If this counter
      69             :   // exceeds the `max_outbound_frames_' value the connection is terminated.
      70             :   uint32_t outbound_frames_ = 0;
      71             :   // Maximum number of outbound frames. Initialized from corresponding http2_protocol_options.
      72             :   // Default value is 10000.
      73             :   const uint32_t max_outbound_frames_;
      74             :   ReleasorProc frame_buffer_releasor_;
      75             : 
      76             :   // This counter keeps track of the number of outbound frames of types PING, SETTINGS and
      77             :   // RST_STREAM (these that were buffered in the underlying connection but not yet written into the
      78             :   // socket). If this counter exceeds the `max_outbound_control_frames_' value the connection is
      79             :   // terminated.
      80             :   uint32_t outbound_control_frames_ = 0;
      81             :   // Maximum number of outbound frames of types PING, SETTINGS and RST_STREAM. Initialized from
      82             :   // corresponding http2_protocol_options. Default value is 1000.
      83             :   const uint32_t max_outbound_control_frames_;
      84             :   ReleasorProc control_frame_buffer_releasor_;
      85             : 
      86             :   // This counter keeps track of the number of consecutive inbound frames of types HEADERS,
      87             :   // CONTINUATION and DATA with an empty payload and no end stream flag. If this counter exceeds
      88             :   // the `max_consecutive_inbound_frames_with_empty_payload_` value the connection is terminated.
      89             :   uint32_t consecutive_inbound_frames_with_empty_payload_ = 0;
      90             :   // Maximum number of consecutive inbound frames of types HEADERS, CONTINUATION and DATA without
      91             :   // a payload. Initialized from corresponding http2_protocol_options. Default value is 1.
      92             :   const uint32_t max_consecutive_inbound_frames_with_empty_payload_;
      93             : 
      94             :   // This counter keeps track of the number of opened streams.
      95             :   // For downstream connection this is incremented when the first HEADERS frame with the new
      96             :   // stream ID is received from the client.
      97             :   // For upstream connections this is incremented when the first HEADERS frame with the new
      98             :   // stream ID is sent to the upstream server.
      99             :   uint32_t opened_streams_ = 0;
     100             :   // This counter keeps track of the number of inbound PRIORITY frames. If this counter exceeds
     101             :   // the value calculated using this formula:
     102             :   //
     103             :   //     max_inbound_priority_frames_per_stream_ * (1 + inbound_streams_)
     104             :   //
     105             :   // the connection is terminated.
     106             :   uint64_t inbound_priority_frames_ = 0;
     107             :   // Maximum number of inbound PRIORITY frames per stream. Initialized from corresponding
     108             :   // http2_protocol_options. Default value is 100.
     109             :   const uint32_t max_inbound_priority_frames_per_stream_;
     110             : 
     111             :   // This counter keeps track of the number of inbound WINDOW_UPDATE frames. If this counter exceeds
     112             :   // the value calculated using this formula:
     113             :   //
     114             :   //     1 + 2 * (inbound_streams_ +
     115             :   //              max_inbound_window_update_frames_per_data_frame_sent_ * outbound_data_frames_)
     116             :   //
     117             :   // the connection is terminated.
     118             :   uint64_t inbound_window_update_frames_ = 0;
     119             :   // This counter keeps track of the number of outbound DATA frames.
     120             :   uint64_t outbound_data_frames_ = 0;
     121             :   // Maximum number of inbound WINDOW_UPDATE frames per outbound DATA frame sent. Initialized
     122             :   // from corresponding http2_protocol_options. Default value is 10.
     123             :   const uint32_t max_inbound_window_update_frames_per_data_frame_sent_;
     124             : };
     125             : 
     126             : } // namespace Http2
     127             : } // namespace Http
     128             : } // namespace Envoy

Generated by: LCOV version 1.15