Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/protobuf/message_validator.h" 4 : #include "envoy/stats/stats.h" 5 : 6 : #include "source/common/common/documentation_url.h" 7 : #include "source/common/common/logger.h" 8 : 9 : #include "absl/container/flat_hash_set.h" 10 : 11 : namespace Envoy { 12 : namespace ProtobufMessage { 13 : 14 : class ValidationVisitorBase : public ValidationVisitor { 15 : public: 16 393 : void setRuntime(Runtime::Loader& runtime) { runtime_ = runtime; } 17 0 : void clearRuntime() { runtime_ = {}; } // for tests 18 12493 : OptRef<Runtime::Loader> runtime() override { return runtime_; } 19 : 20 : protected: 21 : OptRef<Runtime::Loader> runtime_; 22 : }; 23 : 24 : class NullValidationVisitorImpl : public ValidationVisitorBase { 25 : public: 26 : // Envoy::ProtobufMessage::ValidationVisitor 27 0 : void onUnknownField(absl::string_view) override {} 28 0 : void onDeprecatedField(absl::string_view, bool) override {} 29 0 : bool skipValidation() override { return true; } 30 0 : void onWorkInProgress(absl::string_view) override {} 31 : }; 32 : 33 : ValidationVisitor& getNullValidationVisitor(); 34 : 35 : // Base class for both warning and strict validators. 36 : class WipCounterBase { 37 : protected: 38 : void setWipCounter(Stats::Counter& wip_counter); 39 : void onWorkInProgressCommon(absl::string_view description); 40 : 41 : private: 42 : Stats::Counter* wip_counter_{}; 43 : uint64_t prestats_wip_count_{}; 44 : }; 45 : 46 : class WarningValidationVisitorImpl : public ValidationVisitorBase, 47 : public WipCounterBase, 48 : public Logger::Loggable<Logger::Id::config> { 49 : public: 50 : void setCounters(Stats::Counter& unknown_counter, Stats::Counter& wip_counter); 51 : 52 : // Envoy::ProtobufMessage::ValidationVisitor 53 : void onUnknownField(absl::string_view description) override; 54 : void onDeprecatedField(absl::string_view description, bool soft_deprecation) override; 55 0 : bool skipValidation() override { return false; } 56 : void onWorkInProgress(absl::string_view description) override; 57 : 58 : private: 59 : // Track hashes of descriptions we've seen, to avoid log spam. A hash is used here to avoid 60 : // wasting memory with unused strings. 61 : absl::flat_hash_set<uint64_t> descriptions_; 62 : // This can be late initialized via setUnknownCounter(), enabling the server bootstrap loading 63 : // which occurs prior to the initialization of the stats subsystem. 64 : Stats::Counter* unknown_counter_{}; 65 : uint64_t prestats_unknown_count_{}; 66 : }; 67 : 68 : class StrictValidationVisitorImpl : public ValidationVisitorBase, public WipCounterBase { 69 : public: 70 134 : void setCounters(Stats::Counter& wip_counter) { setWipCounter(wip_counter); } 71 : 72 : // Envoy::ProtobufMessage::ValidationVisitor 73 : void onUnknownField(absl::string_view description) override; 74 10725 : bool skipValidation() override { return false; } 75 : void onDeprecatedField(absl::string_view description, bool soft_deprecation) override; 76 : void onWorkInProgress(absl::string_view description) override; 77 : }; 78 : 79 : // TODO(mattklein123): There are various places where the default strict validator is being used. 80 : // This does not increment the WIP stat because nothing calls setCounters() on the stock/static 81 : // version. We should remove this as a public function as well as the stock/static version and 82 : // make sure that all code is either using the server validation context or the null validator. 83 : ValidationVisitor& getStrictValidationVisitor(); 84 : 85 : class ValidationContextImpl : public ValidationContext { 86 : public: 87 : ValidationContextImpl(ValidationVisitor& static_validation_visitor, 88 : ValidationVisitor& dynamic_validation_visitor) 89 : : static_validation_visitor_(static_validation_visitor), 90 455 : dynamic_validation_visitor_(dynamic_validation_visitor) {} 91 : 92 : // Envoy::ProtobufMessage::ValidationContext 93 2362 : ValidationVisitor& staticValidationVisitor() override { return static_validation_visitor_; } 94 809 : ValidationVisitor& dynamicValidationVisitor() override { return dynamic_validation_visitor_; } 95 : 96 : private: 97 : ValidationVisitor& static_validation_visitor_; 98 : ValidationVisitor& dynamic_validation_visitor_; 99 : }; 100 : 101 : class ProdValidationContextImpl : public ValidationContextImpl { 102 : public: 103 : ProdValidationContextImpl(bool allow_unknown_static_fields, bool allow_unknown_dynamic_fields, 104 : bool ignore_unknown_dynamic_fields) 105 : : ValidationContextImpl( 106 : allow_unknown_static_fields 107 : ? static_cast<ValidationVisitor&>(static_warning_validation_visitor_) 108 : : strict_validation_visitor_, 109 : allow_unknown_dynamic_fields 110 : ? (ignore_unknown_dynamic_fields ? ProtobufMessage::getNullValidationVisitor() 111 : : dynamic_warning_validation_visitor_) 112 455 : : strict_validation_visitor_) {} 113 : 114 : void setCounters(Stats::Counter& static_unknown_counter, Stats::Counter& dynamic_unknown_counter, 115 134 : Stats::Counter& wip_counter) { 116 134 : strict_validation_visitor_.setCounters(wip_counter); 117 134 : static_warning_validation_visitor_.setCounters(static_unknown_counter, wip_counter); 118 134 : dynamic_warning_validation_visitor_.setCounters(dynamic_unknown_counter, wip_counter); 119 134 : } 120 : 121 131 : void setRuntime(Runtime::Loader& runtime) { 122 131 : strict_validation_visitor_.setRuntime(runtime); 123 131 : static_warning_validation_visitor_.setRuntime(runtime); 124 131 : dynamic_warning_validation_visitor_.setRuntime(runtime); 125 131 : } 126 : 127 : private: 128 : StrictValidationVisitorImpl strict_validation_visitor_; 129 : ProtobufMessage::WarningValidationVisitorImpl static_warning_validation_visitor_; 130 : ProtobufMessage::WarningValidationVisitorImpl dynamic_warning_validation_visitor_; 131 : }; 132 : 133 : } // namespace ProtobufMessage 134 : } // namespace Envoy