1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
6 #define NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
7 
8 #include <cstdint>
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "base/export_template.h"
15 #include "base/optional.h"
16 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
17 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
18 
19 #define QUIC_FLAG(flag, value) QUIC_EXPORT_PRIVATE extern bool flag;
20 #include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
21 #undef QUIC_FLAG
22 
23 #define QUIC_PROTOCOL_FLAG(type, flag, ...) \
24   QUIC_EXPORT_PRIVATE extern type FLAGS_##flag;
25 #include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
26 #undef QUIC_PROTOCOL_FLAG
27 
28 namespace base {
29 class CommandLine;
30 template <typename T>
31 class NoDestructor;
32 }  // namespace base
33 
34 // API compatibility with new-style flags.
35 
GetQuicFlagImpl(bool flag)36 inline bool GetQuicFlagImpl(bool flag) {
37   return flag;
38 }
GetQuicFlagImpl(int32_t flag)39 inline int32_t GetQuicFlagImpl(int32_t flag) {
40   return flag;
41 }
GetQuicFlagImpl(int64_t flag)42 inline int64_t GetQuicFlagImpl(int64_t flag) {
43   return flag;
44 }
GetQuicFlagImpl(uint64_t flag)45 inline uint64_t GetQuicFlagImpl(uint64_t flag) {
46   return flag;
47 }
GetQuicFlagImpl(double flag)48 inline double GetQuicFlagImpl(double flag) {
49   return flag;
50 }
GetQuicFlagImpl(const std::string & flag)51 inline std::string GetQuicFlagImpl(const std::string& flag) {
52   return flag;
53 }
54 
55 #define SetQuicFlagImpl(flag, value) ((flag) = (value))
56 
57 // Sets the flag named |flag_name| to the value of |value| after converting
58 // it from a string to the appropriate type. If |value| is invalid or out of
59 // range, the flag will be unchanged.
60 QUIC_EXPORT_PRIVATE void SetQuicFlagByName(const std::string& flag_name,
61                                            const std::string& value);
62 
63 namespace quic {
64 
65 // ------------------------------------------------------------------------
66 // DEFINE_QUIC_COMMAND_LINE_FLAG implementation.
67 // ------------------------------------------------------------------------
68 
69 // Abstract class for setting flags and fetching help strings.
70 class QuicFlagHelper {
71  public:
QuicFlagHelper(const char * help)72   explicit QuicFlagHelper(const char* help) : help_(help) {}
73   virtual ~QuicFlagHelper() = default;
74 
75   virtual bool SetFlag(const std::string& value) const = 0;
76   virtual void ResetFlag() const = 0;
GetHelp()77   std::string GetHelp() const { return help_; }
78 
79  private:
80   std::string help_;
81 };
82 
83 // Templated class for setting flags of various types.
84 template <typename T>
85 class TypedQuicFlagHelper : public QuicFlagHelper {
86  public:
TypedQuicFlagHelper(T * flag,const T & default_value,const char * help)87   TypedQuicFlagHelper(T* flag, const T& default_value, const char* help)
88       : QuicFlagHelper(help), flag_(flag), default_value_(default_value) {}
89   bool SetFlag(const std::string& value) const override;
ResetFlag()90   void ResetFlag() const override { *flag_ = default_value_; }
91 
92  private:
93   mutable T* flag_;
94   T default_value_;
95 };
96 
97 // SetFlag specializations. Implementations in .cc file.
98 template <>
99 QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<bool>::SetFlag(
100     const std::string&) const;
101 template <>
102 QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<int32_t>::SetFlag(
103     const std::string&) const;
104 template <>
105 QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<std::string>::SetFlag(
106     const std::string&) const;
107 
108 // TypedQuicFlagHelper instantiations are in .cc file.
109 extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
110     TypedQuicFlagHelper<bool>;
111 extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
112     TypedQuicFlagHelper<int32_t>;
113 extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
114     TypedQuicFlagHelper<std::string>;
115 
116 // Registry of QuicFlagHelpers.
117 class QUIC_EXPORT_PRIVATE QuicFlagRegistry {
118  public:
119   ~QuicFlagRegistry();
120 
121   static QuicFlagRegistry& GetInstance();
122 
123   // Adds a flag to the registry.
124   void RegisterFlag(const char* name, std::unique_ptr<QuicFlagHelper> helper);
125 
126   // Sets any flags in the registry that are specified in |command_line|,
127   // returning true iff successful. If there is a failure, e.g. due to an
128   // invalid flag value, returns false and sets |error_msg|.
129   bool SetFlags(const base::CommandLine& command_line,
130                 std::string* error_msg) const;
131 
132   // Resets flags to their default values.
133   void ResetFlags() const;
134 
135   // Returns a help string consisting of the names and help strings of all
136   // registered flags.
137   std::string GetHelp() const;
138 
139  private:
140   friend class base::NoDestructor<QuicFlagRegistry>;
141 
142   // Should only be accessed as a singleton.
143   QuicFlagRegistry();
144 
145   std::map<std::string, std::unique_ptr<QuicFlagHelper>> flags_;
146 };
147 
148 // Class instantiated in DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion,
149 // that registers flag as a side effect of its constructor. Similar in spirit to
150 // absl::flags_internal::FlagRegistrar.
151 template <typename T>
152 class QuicFlagSetup {
153  public:
QuicFlagSetup(T * flag,const char * name,const T & default_value,const char * help)154   QuicFlagSetup(T* flag,
155                 const char* name,
156                 const T& default_value,
157                 const char* help) {
158     QuicFlagRegistry::GetInstance().RegisterFlag(
159         name,
160         std::make_unique<TypedQuicFlagHelper<T>>(flag, default_value, help));
161   }
162   // Allow QuicFlagSetup instance to convert to a bool in
163   // DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, so it can go away.
164   operator bool() const { return true; }
165 };
166 
167 #define DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) \
168   type FLAGS_##name = default_value;                                        \
169   bool FLAGS_no##name =                                                     \
170       quic::QuicFlagSetup<type>(&FLAGS_##name, #name, default_value, help)
171 
172 QUIC_EXPORT_PRIVATE std::vector<std::string> QuicParseCommandLineFlagsImpl(
173     const char* usage,
174     int argc,
175     const char* const* argv);
176 
177 // Used internally by QuicParseCommandLineFlagsImpl(), but exposed here for
178 // testing.
179 struct QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult {
180   QuicParseCommandLineFlagsResult();
181   QuicParseCommandLineFlagsResult(const QuicParseCommandLineFlagsResult&);
182   ~QuicParseCommandLineFlagsResult();
183 
184   std::vector<std::string> non_flag_args;
185   base::Optional<int> exit_status;
186 };
187 
188 QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult
189 QuicParseCommandLineFlagsHelper(const char* usage,
190                                 const base::CommandLine& command_line);
191 
192 QUIC_EXPORT_PRIVATE void QuicPrintCommandLineFlagHelpImpl(const char* usage);
193 
194 // ------------------------------------------------------------------------
195 // QUIC feature flags implementation.
196 // ------------------------------------------------------------------------
197 #define RELOADABLE_FLAG(flag) FLAGS_quic_reloadable_flag_##flag
198 #define RESTART_FLAG(flag) FLAGS_quic_restart_flag_##flag
199 
200 #define GetQuicReloadableFlagImpl(flag) GetQuicFlag(RELOADABLE_FLAG(flag))
201 #define SetQuicReloadableFlagImpl(flag, value) \
202   SetQuicFlag(RELOADABLE_FLAG(flag), value)
203 #define GetQuicRestartFlagImpl(flag) GetQuicFlag(RESTART_FLAG(flag))
204 #define SetQuicRestartFlagImpl(flag, value) \
205   SetQuicFlag(RESTART_FLAG(flag), value)
206 
207 }  // namespace quic
208 #endif  // NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
209