Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/matcher/field_matcher.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "envoy/matcher/matcher.h"
4
5
#include "absl/strings/str_join.h"
6
7
namespace Envoy {
8
namespace Matcher {
9
10
/**
11
 * The result of a field match.
12
 */
13
struct FieldMatchResult {
14
  // Encodes whether we were able to perform the match.
15
  MatchState match_state_;
16
17
  // The result, if matching was completed.
18
  absl::optional<bool> result_;
19
20
  // The unwrapped result. Should only be called if match_state_ == MatchComplete.
21
15.6k
  bool result() const {
22
15.6k
    ASSERT(match_state_ == MatchState::MatchComplete);
23
15.6k
    ASSERT(result_.has_value());
24
15.6k
    return *result_;
25
15.6k
  }
26
};
27
28
/**
29
 * Base class for matching against a single input.
30
 */
31
template <class DataType> class FieldMatcher {
32
public:
33
22.8k
  virtual ~FieldMatcher() = default;
Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>::~FieldMatcher()
Line
Count
Source
33
22.8k
  virtual ~FieldMatcher() = default;
Unexecuted instantiation: Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>::~FieldMatcher()
Unexecuted instantiation: Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>::~FieldMatcher()
34
35
  /**
36
   * Attempts to match against the provided data.
37
   * @returns absl::optional<bool> if matching was possible, the result of the match. Otherwise
38
   * absl::nullopt if the data is not available.
39
   */
40
  virtual FieldMatchResult match(const DataType& data) PURE;
41
};
42
template <class DataType> using FieldMatcherPtr = std::unique_ptr<FieldMatcher<DataType>>;
43
44
/**
45
 * A FieldMatcher that attempts to match multiple FieldMatchers, evaluating to true iff all the
46
 * FieldMatchers evaluate to true.
47
 *
48
 * If any of the underlying FieldMatchers are unable to produce a result, absl::nullopt is returned.
49
 */
50
template <class DataType> class AllFieldMatcher : public FieldMatcher<DataType> {
51
public:
52
  explicit AllFieldMatcher(std::vector<FieldMatcherPtr<DataType>>&& matchers)
53
1.59k
      : matchers_(std::move(matchers)) {}
Envoy::Matcher::AllFieldMatcher<Envoy::Http::HttpMatchingData>::AllFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData> > > > >&&)
Line
Count
Source
53
1.59k
      : matchers_(std::move(matchers)) {}
Unexecuted instantiation: Envoy::Matcher::AllFieldMatcher<Envoy::Network::MatchingData>::AllFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData> > > > >&&)
Unexecuted instantiation: Envoy::Matcher::AllFieldMatcher<Envoy::Network::UdpMatchingData>::AllFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData> > > > >&&)
54
55
990
  FieldMatchResult match(const DataType& data) override {
56
1.61k
    for (const auto& matcher : matchers_) {
57
1.61k
      const auto result = matcher->match(data);
58
59
      // If we are unable to decide on a match at this point, propagate this up to defer
60
      // the match result until we have the requisite data.
61
1.61k
      if (result.match_state_ == MatchState::UnableToMatch) {
62
0
        return result;
63
0
      }
64
65
1.61k
      if (!result.result()) {
66
749
        return result;
67
749
      }
68
1.61k
    }
69
70
241
    return {MatchState::MatchComplete, true};
71
990
  }
Envoy::Matcher::AllFieldMatcher<Envoy::Http::HttpMatchingData>::match(Envoy::Http::HttpMatchingData const&)
Line
Count
Source
55
990
  FieldMatchResult match(const DataType& data) override {
56
1.61k
    for (const auto& matcher : matchers_) {
57
1.61k
      const auto result = matcher->match(data);
58
59
      // If we are unable to decide on a match at this point, propagate this up to defer
60
      // the match result until we have the requisite data.
61
1.61k
      if (result.match_state_ == MatchState::UnableToMatch) {
62
0
        return result;
63
0
      }
64
65
1.61k
      if (!result.result()) {
66
749
        return result;
67
749
      }
68
1.61k
    }
69
70
241
    return {MatchState::MatchComplete, true};
71
990
  }
Unexecuted instantiation: Envoy::Matcher::AllFieldMatcher<Envoy::Network::MatchingData>::match(Envoy::Network::MatchingData const&)
Unexecuted instantiation: Envoy::Matcher::AllFieldMatcher<Envoy::Network::UdpMatchingData>::match(Envoy::Network::UdpMatchingData const&)
72
73
private:
74
  const std::vector<FieldMatcherPtr<DataType>> matchers_;
75
};
76
77
/**
78
 * A FieldMatcher that attempts to match multiple FieldMatchers, evaluating to true iff any of the
79
 * FieldMatchers evaluate to true.
80
 *
81
 * If any of the underlying FieldMatchers are unable to produce a result before we see a successful
82
 * match, absl::nullopt is returned.
83
 */
84
template <class DataType> class AnyFieldMatcher : public FieldMatcher<DataType> {
85
public:
86
  explicit AnyFieldMatcher(std::vector<FieldMatcherPtr<DataType>>&& matchers)
87
3.92k
      : matchers_(std::move(matchers)) {}
Envoy::Matcher::AnyFieldMatcher<Envoy::Http::HttpMatchingData>::AnyFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData> > > > >&&)
Line
Count
Source
87
3.92k
      : matchers_(std::move(matchers)) {}
Unexecuted instantiation: Envoy::Matcher::AnyFieldMatcher<Envoy::Network::MatchingData>::AnyFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData> > > > >&&)
Unexecuted instantiation: Envoy::Matcher::AnyFieldMatcher<Envoy::Network::UdpMatchingData>::AnyFieldMatcher(std::__1::vector<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData> > >, std::__1::allocator<std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData> > > > >&&)
88
89
3.44k
  FieldMatchResult match(const DataType& data) override {
90
3.44k
    bool unable_to_match_some_matchers = false;
91
12.1k
    for (const auto& matcher : matchers_) {
92
12.1k
      const auto result = matcher->match(data);
93
94
12.1k
      if (result.match_state_ == MatchState::UnableToMatch) {
95
0
        unable_to_match_some_matchers = true;
96
0
        continue;
97
0
      }
98
99
12.1k
      if (result.result()) {
100
331
        return {MatchState::MatchComplete, true};
101
331
      }
102
12.1k
    }
103
104
    // If we didn't find a successful match but not all matchers could be evaluated,
105
    // return UnableToMatch to defer the match result.
106
3.11k
    if (unable_to_match_some_matchers) {
107
0
      return {MatchState::UnableToMatch, absl::nullopt};
108
0
    }
109
110
3.11k
    return {MatchState::MatchComplete, false};
111
3.11k
  }
Envoy::Matcher::AnyFieldMatcher<Envoy::Http::HttpMatchingData>::match(Envoy::Http::HttpMatchingData const&)
Line
Count
Source
89
3.44k
  FieldMatchResult match(const DataType& data) override {
90
3.44k
    bool unable_to_match_some_matchers = false;
91
12.1k
    for (const auto& matcher : matchers_) {
92
12.1k
      const auto result = matcher->match(data);
93
94
12.1k
      if (result.match_state_ == MatchState::UnableToMatch) {
95
0
        unable_to_match_some_matchers = true;
96
0
        continue;
97
0
      }
98
99
12.1k
      if (result.result()) {
100
331
        return {MatchState::MatchComplete, true};
101
331
      }
102
12.1k
    }
103
104
    // If we didn't find a successful match but not all matchers could be evaluated,
105
    // return UnableToMatch to defer the match result.
106
3.11k
    if (unable_to_match_some_matchers) {
107
0
      return {MatchState::UnableToMatch, absl::nullopt};
108
0
    }
109
110
3.11k
    return {MatchState::MatchComplete, false};
111
3.11k
  }
Unexecuted instantiation: Envoy::Matcher::AnyFieldMatcher<Envoy::Network::MatchingData>::match(Envoy::Network::MatchingData const&)
Unexecuted instantiation: Envoy::Matcher::AnyFieldMatcher<Envoy::Network::UdpMatchingData>::match(Envoy::Network::UdpMatchingData const&)
112
113
private:
114
  const std::vector<FieldMatcherPtr<DataType>> matchers_;
115
};
116
117
/**
118
 * A FieldMatcher that returns the invert of a FieldMatcher.
119
 */
120
template <class DataType> class NotFieldMatcher : public FieldMatcher<DataType> {
121
public:
122
1.57k
  explicit NotFieldMatcher(FieldMatcherPtr<DataType> matcher) : matcher_(std::move(matcher)) {}
Envoy::Matcher::NotFieldMatcher<Envoy::Http::HttpMatchingData>::NotFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Http::HttpMatchingData> > >)
Line
Count
Source
122
1.57k
  explicit NotFieldMatcher(FieldMatcherPtr<DataType> matcher) : matcher_(std::move(matcher)) {}
Unexecuted instantiation: Envoy::Matcher::NotFieldMatcher<Envoy::Network::MatchingData>::NotFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::MatchingData> > >)
Unexecuted instantiation: Envoy::Matcher::NotFieldMatcher<Envoy::Network::UdpMatchingData>::NotFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::FieldMatcher<Envoy::Network::UdpMatchingData> > >)
123
124
953
  FieldMatchResult match(const DataType& data) override {
125
953
    const auto result = matcher_->match(data);
126
953
    if (result.match_state_ == MatchState::UnableToMatch) {
127
0
      return result;
128
0
    }
129
130
953
    return {MatchState::MatchComplete, !result.result()};
131
953
  }
Envoy::Matcher::NotFieldMatcher<Envoy::Http::HttpMatchingData>::match(Envoy::Http::HttpMatchingData const&)
Line
Count
Source
124
953
  FieldMatchResult match(const DataType& data) override {
125
953
    const auto result = matcher_->match(data);
126
953
    if (result.match_state_ == MatchState::UnableToMatch) {
127
0
      return result;
128
0
    }
129
130
953
    return {MatchState::MatchComplete, !result.result()};
131
953
  }
Unexecuted instantiation: Envoy::Matcher::NotFieldMatcher<Envoy::Network::MatchingData>::match(Envoy::Network::MatchingData const&)
Unexecuted instantiation: Envoy::Matcher::NotFieldMatcher<Envoy::Network::UdpMatchingData>::match(Envoy::Network::UdpMatchingData const&)
132
133
private:
134
  const FieldMatcherPtr<DataType> matcher_;
135
};
136
137
/**
138
 * Implementation of a FieldMatcher that extracts an input value from the provided data and attempts
139
 * to match using an InputMatcher. absl::nullopt is returned whenever the data is not available or
140
 * if we failed to match and there is more data available.
141
 * A consequence of this is that if a match result is desired, care should be taken so that matching
142
 * is done with all the data available at some point.
143
 */
144
template <class DataType>
145
class SingleFieldMatcher : public FieldMatcher<DataType>, Logger::Loggable<Logger::Id::matcher> {
146
public:
147
  SingleFieldMatcher(DataInputPtr<DataType>&& data_input, InputMatcherPtr&& input_matcher)
148
15.7k
      : data_input_(std::move(data_input)), input_matcher_(std::move(input_matcher)) {
149
15.7k
    auto supported_input_types = input_matcher_->supportedDataInputTypes();
150
15.7k
    if (supported_input_types.find(data_input_->dataInputType()) == supported_input_types.end()) {
151
0
      std::string supported_types =
152
0
          absl::StrJoin(supported_input_types.begin(), supported_input_types.end(), ", ");
153
0
      throwEnvoyExceptionOrPanic(
154
0
          absl::StrCat("Unsupported data input type: ", data_input_->dataInputType(),
155
0
                       ". The matcher supports input type: ", supported_types));
156
0
    }
157
15.7k
  }
Envoy::Matcher::SingleFieldMatcher<Envoy::Http::HttpMatchingData>::SingleFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::DataInput<Envoy::Http::HttpMatchingData>, std::__1::default_delete<Envoy::Matcher::DataInput<Envoy::Http::HttpMatchingData> > >&&, std::__1::unique_ptr<Envoy::Matcher::InputMatcher, std::__1::default_delete<Envoy::Matcher::InputMatcher> >&&)
Line
Count
Source
148
15.7k
      : data_input_(std::move(data_input)), input_matcher_(std::move(input_matcher)) {
149
15.7k
    auto supported_input_types = input_matcher_->supportedDataInputTypes();
150
15.7k
    if (supported_input_types.find(data_input_->dataInputType()) == supported_input_types.end()) {
151
0
      std::string supported_types =
152
0
          absl::StrJoin(supported_input_types.begin(), supported_input_types.end(), ", ");
153
0
      throwEnvoyExceptionOrPanic(
154
0
          absl::StrCat("Unsupported data input type: ", data_input_->dataInputType(),
155
0
                       ". The matcher supports input type: ", supported_types));
156
0
    }
157
15.7k
  }
Unexecuted instantiation: Envoy::Matcher::SingleFieldMatcher<Envoy::Network::MatchingData>::SingleFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::DataInput<Envoy::Network::MatchingData>, std::__1::default_delete<Envoy::Matcher::DataInput<Envoy::Network::MatchingData> > >&&, std::__1::unique_ptr<Envoy::Matcher::InputMatcher, std::__1::default_delete<Envoy::Matcher::InputMatcher> >&&)
Unexecuted instantiation: Envoy::Matcher::SingleFieldMatcher<Envoy::Network::UdpMatchingData>::SingleFieldMatcher(std::__1::unique_ptr<Envoy::Matcher::DataInput<Envoy::Network::UdpMatchingData>, std::__1::default_delete<Envoy::Matcher::DataInput<Envoy::Network::UdpMatchingData> > >&&, std::__1::unique_ptr<Envoy::Matcher::InputMatcher, std::__1::default_delete<Envoy::Matcher::InputMatcher> >&&)
158
159
10.2k
  FieldMatchResult match(const DataType& data) override {
160
10.2k
    const auto input = data_input_->get(data);
161
162
10.2k
    ENVOY_LOG(trace, "Attempting to match {}", input);
163
10.2k
    if (input.data_availability_ == DataInputGetResult::DataAvailability::NotAvailable) {
164
0
      return {MatchState::UnableToMatch, absl::nullopt};
165
0
    }
166
167
10.2k
    bool current_match = input_matcher_->match(input.data_);
168
10.2k
    if (!current_match && input.data_availability_ ==
169
9.55k
                              DataInputGetResult::DataAvailability::MoreDataMightBeAvailable) {
170
0
      ENVOY_LOG(trace, "No match yet; delaying result as more data might be available.");
171
0
      return {MatchState::UnableToMatch, absl::nullopt};
172
0
    }
173
174
10.2k
    ENVOY_LOG(trace, "Match result: {}", current_match);
175
176
10.2k
    return {MatchState::MatchComplete, current_match};
177
10.2k
  }
Envoy::Matcher::SingleFieldMatcher<Envoy::Http::HttpMatchingData>::match(Envoy::Http::HttpMatchingData const&)
Line
Count
Source
159
10.2k
  FieldMatchResult match(const DataType& data) override {
160
10.2k
    const auto input = data_input_->get(data);
161
162
10.2k
    ENVOY_LOG(trace, "Attempting to match {}", input);
163
10.2k
    if (input.data_availability_ == DataInputGetResult::DataAvailability::NotAvailable) {
164
0
      return {MatchState::UnableToMatch, absl::nullopt};
165
0
    }
166
167
10.2k
    bool current_match = input_matcher_->match(input.data_);
168
10.2k
    if (!current_match && input.data_availability_ ==
169
9.55k
                              DataInputGetResult::DataAvailability::MoreDataMightBeAvailable) {
170
0
      ENVOY_LOG(trace, "No match yet; delaying result as more data might be available.");
171
0
      return {MatchState::UnableToMatch, absl::nullopt};
172
0
    }
173
174
10.2k
    ENVOY_LOG(trace, "Match result: {}", current_match);
175
176
10.2k
    return {MatchState::MatchComplete, current_match};
177
10.2k
  }
Unexecuted instantiation: Envoy::Matcher::SingleFieldMatcher<Envoy::Network::MatchingData>::match(Envoy::Network::MatchingData const&)
Unexecuted instantiation: Envoy::Matcher::SingleFieldMatcher<Envoy::Network::UdpMatchingData>::match(Envoy::Network::UdpMatchingData const&)
178
179
private:
180
  const DataInputPtr<DataType> data_input_;
181
  const InputMatcherPtr input_matcher_;
182
};
183
184
template <class DataType>
185
using SingleFieldMatcherPtr = std::unique_ptr<SingleFieldMatcher<DataType>>;
186
} // namespace Matcher
187
} // namespace Envoy