xref: /openbmc/bmcweb/COMMON_ERRORS.md (revision 9e2d2033ba1a53401c04ebb7a33da9df06d52272)
1bafb82b2SEd Tanous# Commonly recurring errors in bmcweb
2bafb82b2SEd Tanous
3bafb82b2SEd TanousWhat follows is a list of common errors that new users to bmcweb tend to make
4bafb82b2SEd Tanouswhen operating within its bounds for the first time. If this is your first time
5bafb82b2SEd Tanousdeveloping in bmcweb, the maintainers highly recommend reading and understanding
6bafb82b2SEd Tanous_all_ of common traps before continuing with any development. Every single one
7bafb82b2SEd Tanousof the examples below compile without warnings, but are incorrect in
8bafb82b2SEd Tanousnot-always-obvious ways, or impose a pattern that tends to cause hard to find
9bafb82b2SEd Tanousbugs, or bugs that appear later. Every one has been submitted to code review
10bafb82b2SEd Tanousmultiple times.
11bafb82b2SEd Tanous
12f4f2643aSPatrick Williams## 1. Directly dereferencing a pointer without checking for validity first
13dfa3fdc3SPatrick Williams
14f4f2643aSPatrick Williams```cpp
15bafb82b2SEd Tanousint myBadMethod(const nlohmann::json& j){
16bafb82b2SEd Tanous    const int* myPtr = j.get_if<int>();
17bafb82b2SEd Tanous    return *myPtr;
18bafb82b2SEd Tanous}
19bafb82b2SEd Tanous```
20dfa3fdc3SPatrick Williams
21bafb82b2SEd TanousThis pointer is not guaranteed to be filled, and could be a null dereference.
22bafb82b2SEd Tanous
23f4f2643aSPatrick Williams## 2. String views aren't null terminated
24dfa3fdc3SPatrick Williams
25f4f2643aSPatrick Williams```cpp
2626ccae32SEd Tanousint getIntFromString(std::string_view s){
27bafb82b2SEd Tanous    return std::atoi(s.data());
28bafb82b2SEd Tanous}
29bafb82b2SEd Tanous```
30dfa3fdc3SPatrick Williams
31bafb82b2SEd TanousThis will give the right answer much of the time, but has the possibility to
32f4f2643aSPatrick Williamsfail when `string_view` is not null terminated. Use `from_chars` instead, which
33bafb82b2SEd Tanoustakes both a pointer and a length
34bafb82b2SEd Tanous
35f4f2643aSPatrick Williams## 3. Not handling input errors
36dfa3fdc3SPatrick Williams
37f4f2643aSPatrick Williams```cpp
38bafb82b2SEd Tanousint getIntFromString(const std::string& s){
39bafb82b2SEd Tanous    return std::atoi(s.c_str());
40bafb82b2SEd Tanous}
41bafb82b2SEd Tanous```
42dfa3fdc3SPatrick Williams
43bafb82b2SEd TanousIn the case where the string is not representable as an int, this will trigger
44bafb82b2SEd Tanousundefined behavior at system level. Code needs to check for validity of the
45f4f2643aSPatrick Williamsstring, ideally with something like `from_chars`, and return the appropriate
46f4f2643aSPatrick Williamserror code.
47bafb82b2SEd Tanous
48f4f2643aSPatrick Williams## 4. Walking off the end of a string
49dfa3fdc3SPatrick Williams
50f4f2643aSPatrick Williams```cpp
51bafb82b2SEd Tanousstd::string getFilenameFromPath(const std::string& path){
52bafb82b2SEd Tanous    size_t index = path.find("/");
53bafb82b2SEd Tanous    if (index != std::string::npos){
54bafb82b2SEd Tanous        // If the string ends with "/", this will walk off the end of the string.
55bafb82b2SEd Tanous        return path.substr(pos + 1);
56bafb82b2SEd Tanous    }
57bafb82b2SEd Tanous    return "";
58bafb82b2SEd Tanous}
59bafb82b2SEd Tanous```
60bafb82b2SEd Tanous
61f4f2643aSPatrick Williams## 5. Using methods that throw (or not handling bad inputs)
62dfa3fdc3SPatrick Williams
63f4f2643aSPatrick Williams```cpp
64bafb82b2SEd Tanousint myBadMethod(nlohmann::json& j){
65bafb82b2SEd Tanous    return j.get<int>();
66bafb82b2SEd Tanous}
67bafb82b2SEd Tanous```
68dfa3fdc3SPatrick Williams
69bafb82b2SEd TanousThis method throws, and bad inputs will not be handled
70bafb82b2SEd Tanous
71bafb82b2SEd TanousCommonly used methods that fall into this pattern:
72929d4b57SGunnar Mills
73929d4b57SGunnar Mills- std::variant::get
74929d4b57SGunnar Mills- std::vector::at
75929d4b57SGunnar Mills- std::map::at
76929d4b57SGunnar Mills- std::set::at
77929d4b57SGunnar Mills- std::\<generic container type\>::at
78929d4b57SGunnar Mills- nlohmann::json::operator!=
79929d4b57SGunnar Mills- nlohmann::json::operator+=
80929d4b57SGunnar Mills- nlohmann::json::at
81929d4b57SGunnar Mills- nlohmann::json::get
82dfa3fdc3SPatrick Williams- nlohmann::json::get_ref
83dfa3fdc3SPatrick Williams- nlohmann::json::get_to
840bdda665SEd Tanous- nlohmann::json::items
85c5114a57SJosh Lehan- nlohmann::json::operator\<\<
86c5114a57SJosh Lehan- nlohmann::json::operator\>\>
87dfa3fdc3SPatrick Williams- std::filesystem::create_directory
88929d4b57SGunnar Mills- std::filesystem::rename
89dfa3fdc3SPatrick Williams- std::filesystem::file_size
90929d4b57SGunnar Mills- std::stoi
91929d4b57SGunnar Mills- std::stol
92929d4b57SGunnar Mills- std::stoll
93bafb82b2SEd Tanous
94f4f2643aSPatrick Williams### Special note: JSON
95bafb82b2SEd Tanous
96c5114a57SJosh Lehan`nlohmann::json::parse` by default
97dfa3fdc3SPatrick Williams[throws](https://json.nlohmann.me/api/basic_json/parse/) on failure, but also
98dfa3fdc3SPatrick Williamsaccepts an optional argument that causes it to not throw: set the 3rd argument
99dfa3fdc3SPatrick Williamsto `false`.
100bafb82b2SEd Tanous
101c5114a57SJosh Lehan`nlohmann::json::dump` by default
102c5114a57SJosh Lehan[throws](https://json.nlohmann.me/api/basic_json/dump/) on failure, but also
103dfa3fdc3SPatrick Williamsaccepts an optional argument that causes it to not throw: set the 4th argument
104dfa3fdc3SPatrick Williamsto `replace`. Although `ignore` preserves content 1:1, `replace` is preferred
105dfa3fdc3SPatrick Williamsfrom a security point of view.
106bafb82b2SEd Tanous
107f4f2643aSPatrick Williams### Special note: Boost
108dfa3fdc3SPatrick Williams
109bafb82b2SEd Tanousthere is a whole class of boost asio functions that provide both a method that
110bafb82b2SEd Tanousthrows on failure, and a method that accepts and returns an error code. This is
111bafb82b2SEd Tanousnot a complete list, but users should verify in the boost docs when calling into
112bafb82b2SEd Tanousasio methods, and prefer the one that returns an error code instead of throwing.
113bafb82b2SEd Tanous
114929d4b57SGunnar Mills- boost::asio::ip::tcp::acceptor::bind();
115929d4b57SGunnar Mills- boost::asio::ip::tcp::acceptor::cancel();
116929d4b57SGunnar Mills- boost::asio::ip::tcp::acceptor::close();
117929d4b57SGunnar Mills- boost::asio::ip::tcp::acceptor::listen();
118dfa3fdc3SPatrick Williams- boost::asio::ip::address::make_address();
119bafb82b2SEd Tanous
120f4f2643aSPatrick Williams## 6. Blocking functions
121bafb82b2SEd Tanous
122bafb82b2SEd Tanousbmcweb uses a single reactor for all operations. Blocking that reactor for any
123bafb82b2SEd Tanousamount of time causes all other operations to stop. The common blocking
124bafb82b2SEd Tanousfunctions that tend to be called incorrectly are:
125bafb82b2SEd Tanous
126929d4b57SGunnar Mills- sleep()
127929d4b57SGunnar Mills- boost::asio::ip::tcp::socket::read()
128dfa3fdc3SPatrick Williams- boost::asio::ip::tcp::socket::read_some()
129929d4b57SGunnar Mills- boost::asio::ip::tcp::socket::write()
130dfa3fdc3SPatrick Williams- boost::asio::ip::tcp::socket::write_some()
131929d4b57SGunnar Mills- boost::asio::ip::tcp::socket::connect()
132929d4b57SGunnar Mills- boost::asio::ip::tcp::socket::send()
133929d4b57SGunnar Mills- boost::asio::ip::tcp::socket::wait()
134dfa3fdc3SPatrick Williams- boost::asio::steady_timer::wait()
135bafb82b2SEd Tanous
136dfa3fdc3SPatrick WilliamsNote: an exception is made for filesystem/disk IO read and write. This is mostly
137dfa3fdc3SPatrick Williamsdue to not having great abstractions for it that mate well with the async
138bafb82b2SEd Tanoussystem, the fact that most filesystem accesses are into tmpfs (and therefore
139bafb82b2SEd Tanousshould be "fast" most of the time) and in general how little the filesystem is
140bafb82b2SEd Tanousused in practice.
141bafb82b2SEd Tanous
142f4f2643aSPatrick Williams## 7. Lack of locking between subsequent calls
143dfa3fdc3SPatrick Williams
144bafb82b2SEd TanousWhile global data structures are discouraged, they are sometimes required to
145dfa3fdc3SPatrick Williamsstore temporary state for operations that require it. Given the single threaded
146dfa3fdc3SPatrick Williamsnature of bmcweb, they are not required to be explicitly threadsafe, but they
147dfa3fdc3SPatrick Williamsmust be always left in a valid state, and checked for other uses before
148dfa3fdc3SPatrick Williamsoccupying.
149bafb82b2SEd Tanous
150f4f2643aSPatrick Williams```cpp
151bafb82b2SEd Tanousstd::optional<std::string> currentOperation;
152bafb82b2SEd Tanousvoid firstCallbackInFlow(){
153bafb82b2SEd Tanous    currentOperation = "Foo";
154bafb82b2SEd Tanous}
155bafb82b2SEd Tanousvoid secondCallbackInFlow(){
156bafb82b2SEd Tanous    currentOperation.reset();
157bafb82b2SEd Tanous}
158bafb82b2SEd Tanous```
159bafb82b2SEd Tanous
160bafb82b2SEd TanousIn the above case, the first callback needs a check to ensure that
161bafb82b2SEd TanouscurrentOperation is not already being used.
162bafb82b2SEd Tanous
163f4f2643aSPatrick Williams## 8. Wildcard reference captures in lambdas
164dfa3fdc3SPatrick Williams
165f4f2643aSPatrick Williams```cpp
166bafb82b2SEd Tanousstd::string x; auto mylambda = [&](){
167bafb82b2SEd Tanous    x = "foo";
168bafb82b2SEd Tanous}
169bafb82b2SEd Tanousdo_async_read(mylambda)
170bafb82b2SEd Tanous```
171bafb82b2SEd Tanous
172bafb82b2SEd TanousNumerous times, lifetime issues of const references have been injected into
173bafb82b2SEd Tanousasync bmcweb code. While capturing by reference can be useful, given how
174bafb82b2SEd Tanousdifficult these types of bugs are to triage, bmcweb explicitly requires that all
175bafb82b2SEd Tanouscode captures variables by name explicitly, and calls out each variable being
176bafb82b2SEd Tanouscaptured by value or by reference. The above prototypes would change to
177f4f2643aSPatrick Williams`[&x]()...` Which makes clear that x is captured, and its lifetime needs
178f4f2643aSPatrick Williamstracked.
179bafb82b2SEd Tanous
180f4f2643aSPatrick Williams## 9. URLs should end in "/"
181dfa3fdc3SPatrick Williams
182f4f2643aSPatrick Williams```cpp
183bafb82b2SEd TanousBMCWEB("/foo/bar");
184bafb82b2SEd Tanous```
185dfa3fdc3SPatrick Williams
186bafb82b2SEd TanousUnless you explicitly have a reason not to (as there is one known exception
187bafb82b2SEd Tanouswhere the behavior must differ) all URL handlers should end in "/". The bmcweb
188bafb82b2SEd Tanousroute handler will detect routes ending in slash and generate routes for both
189dfa3fdc3SPatrick Williamsthe route ending in slash and the one without. This allows both URLs to be used
190dfa3fdc3SPatrick Williamsby users. While many specifications do not require this, it resolves a whole
191dfa3fdc3SPatrick Williamsclass of bug that we've seen in the past.
192bafb82b2SEd Tanous
193e9f12014SEd TanousNote, unit tests can now find this for redfish routes.
194e9f12014SEd Tanous
195f4f2643aSPatrick Williams## 10. URLs constructed in aggregate
196dfa3fdc3SPatrick Williams
197f4f2643aSPatrick Williams```cpp
198bafb82b2SEd Tanousstd::string routeStart = "/redfish/v1";
199bafb82b2SEd Tanous
200bafb82b2SEd TanousBMCWEB_ROUTE(routestart + "/SessionService/")
201bafb82b2SEd Tanous```
202dfa3fdc3SPatrick Williams
203bafb82b2SEd TanousVery commonly, bmcweb maintainers and contributors alike have to do audits of
204bafb82b2SEd Tanousall routes that are available, to verify things like security and documentation
205dfa3fdc3SPatrick Williamsaccuracy. While these processes are largely manual, they can mostly be conducted
206dfa3fdc3SPatrick Williamsby a simple grep statement to search for urls in question. Doing the above makes
207dfa3fdc3SPatrick Williamsthe route handlers no longer greppable, and complicates bmcweb patchsets as a
208dfa3fdc3SPatrick Williamswhole.
209ae6595efSEd Tanous
210f4f2643aSPatrick Williams## 11. Not responding to 404
211dfa3fdc3SPatrick Williams
212f4f2643aSPatrick Williams```cpp
213ae6595efSEd TanousBMCWEB_ROUTE("/myendpoint/<str>",
214ae6595efSEd Tanous    [](Request& req, Response& res, const std::string& id){
215ae6595efSEd Tanous     crow::connections::systemBus->async_method_call(
2165e7e2dc5SEd Tanous          [asyncResp](const boost::system::error_code& ec,
217ae6595efSEd Tanous                      const std::string& myProperty) {
218ae6595efSEd Tanous              if (ec)
219ae6595efSEd Tanous              {
220ae6595efSEd Tanous                  messages::internalError(asyncResp->res);
221ae6595efSEd Tanous                  return;
222ae6595efSEd Tanous              }
223ae6595efSEd Tanous              ... handle code
224ae6595efSEd Tanous          },
225ae6595efSEd Tanous          "xyz.openbmc_project.Logging",
226ae6595efSEd Tanous          "/xyz/openbmc_project/mypath/" + id,
227ae6595efSEd Tanous          "xyz.MyInterface", "GetAll", "");
228ae6595efSEd Tanous});
229ae6595efSEd Tanous```
230dfa3fdc3SPatrick Williams
231ae6595efSEd TanousAll bmcweb routes should handle 404 (not found) properly, and return it where
232dfa3fdc3SPatrick Williamsappropriate. 500 internal error is not a substitute for this, and should be only
233dfa3fdc3SPatrick Williamsused if there isn't a more appropriate error code that can be returned. This is
234dfa3fdc3SPatrick Williamsimportant, because a number of vulnerability scanners attempt injection attacks
235f4f2643aSPatrick Williamsin the form of `/myendpoint/foobar`, or `/myendpoint/#$*(%)&#%$)(\*&` in an
236f4f2643aSPatrick Williamsattempt to circumvent security. If the server returns 500 to any of these
237f4f2643aSPatrick Williamsrequests, the security scanner logs it as an error for followup. While in
238f4f2643aSPatrick Williamsgeneral these errors are benign, and not actually a real security threat, having
239f4f2643aSPatrick Williamsa clean security run allows maintainers to minimize the amount of time spent
240f4f2643aSPatrick Williamstriaging issues reported from these scanning tools.
241ae6595efSEd Tanous
24280be2cdbSAbhishek PatelAn implementation of the above that handles 404 would look like:
243dfa3fdc3SPatrick Williams
244f4f2643aSPatrick Williams```cpp
245ae6595efSEd TanousBMCWEB_ROUTE("/myendpoint/<str>",
246ae6595efSEd Tanous    [](Request& req, Response& res, const std::string& id){
247ae6595efSEd Tanous     crow::connections::systemBus->async_method_call(
2485e7e2dc5SEd Tanous          [asyncResp](const boost::system::error_code& ec,
249ae6595efSEd Tanous                      const std::string& myProperty) {
250ae6595efSEd Tanous              if (ec == <error code that gets returned by not found>){
251ae6595efSEd Tanous                  messages::resourceNotFound(res);
252ae6595efSEd Tanous                  return;
253ae6595efSEd Tanous              }
254ae6595efSEd Tanous              if (ec)
255ae6595efSEd Tanous              {
256ae6595efSEd Tanous                  messages::internalError(asyncResp->res);
257ae6595efSEd Tanous                  return;
258ae6595efSEd Tanous              }
259ae6595efSEd Tanous              ... handle code
260ae6595efSEd Tanous          },
261ae6595efSEd Tanous          "xyz.openbmc_project.Logging",
262ae6595efSEd Tanous          "/xyz/openbmc_project/mypath/" + id,
263ae6595efSEd Tanous          "xyz.MyInterface", "GetAll", "");
264ae6595efSEd Tanous});
265ae6595efSEd Tanous```
266ae6595efSEd Tanous
267ae6595efSEd TanousNote: A more general form of this rule is that no handler should ever return 500
268ae6595efSEd Tanouson a working system, and any cases where 500 is found, can immediately be
269dfa3fdc3SPatrick Williamsassumed to be
270dfa3fdc3SPatrick Williams[a bug in either the system, or bmcweb.](https://github.com/openbmc/bmcweb/blob/master/DEVELOPING.md#error-handling)
2710c15c33eSEd Tanous
272f4f2643aSPatrick Williams## 12. Imprecise matching
273dfa3fdc3SPatrick Williams
274f4f2643aSPatrick Williams```cpp
2750c15c33eSEd Tanousvoid isInventoryPath(const std::string& path){
2760c15c33eSEd Tanous    if (path.find("inventory")){
2770c15c33eSEd Tanous        return true;
2780c15c33eSEd Tanous    }
2790c15c33eSEd Tanous    return false;
2800c15c33eSEd Tanous}
2810c15c33eSEd Tanous```
282dfa3fdc3SPatrick Williams
2830c15c33eSEd TanousWhen matching dbus paths, HTTP fields, interface names, care should be taken to
2840c15c33eSEd Tanousavoid doing direct string containment matching. Doing so can lead to errors
2850c15c33eSEd Tanouswhere fan1 and fan11 both report to the same object, and cause behavior breaks
2860c15c33eSEd Tanousin subtle ways.
2870c15c33eSEd Tanous
288f4f2643aSPatrick WilliamsWhen using dbus paths, rely on the methods on `sdbusplus::message::object_path`.
2890c15c33eSEd TanousWhen parsing HTTP field and lists, use the RFC7230 implementations from
2900c15c33eSEd Tanousboost::beast.
2910c15c33eSEd Tanous
292dfa3fdc3SPatrick WilliamsOther commonly misused methods are: boost::iequals. Unless the standard you're
293dfa3fdc3SPatrick Williamsimplementing (as is the case in some HTTP fields) requires case insensitive
294dfa3fdc3SPatrick Williamscomparisons, casing should be obeyed, especially when relying on user-driven
295dfa3fdc3SPatrick Williamsdata.
2960c15c33eSEd Tanous
297dfa3fdc3SPatrick Williams- boost::starts_with
298dfa3fdc3SPatrick Williams- boost::ends_with
299dfa3fdc3SPatrick Williams- std::string::starts_with
300dfa3fdc3SPatrick Williams- std::string::ends_with
3010c15c33eSEd Tanous- std::string::rfind
3020c15c33eSEd Tanous
3030c15c33eSEd TanousThe above methods tend to be misused to accept user data and parse various
304dfa3fdc3SPatrick Williamsfields from it. In practice, there tends to be better, purpose built methods for
305dfa3fdc3SPatrick Williamsremoving just the field you need.
306d02420b2SEd Tanous
307f4f2643aSPatrick Williams## 13. Complete replacement of the response object
308d02420b2SEd Tanous
309f4f2643aSPatrick Williams```cpp
310d02420b2SEd Tanousvoid getMembers(crow::Response& res){
311d02420b2SEd Tanous  res.jsonValue = {{"Value", 2}};
312d02420b2SEd Tanous}
313d02420b2SEd Tanous```
314d02420b2SEd Tanous
315d02420b2SEd TanousIn many cases, bmcweb is doing multiple async actions in parallel, and
316dfa3fdc3SPatrick Williamsorthogonal keys within the Response object might be filled in from another task.
317dfa3fdc3SPatrick WilliamsCompletely replacing the json object can lead to convoluted situations where the
318dfa3fdc3SPatrick Williamsoutput of the response is dependent on the _order_ of the asynchronous actions
319dfa3fdc3SPatrick Williamscompleting, which cannot be guaranteed, and has many time caused bugs.
320d02420b2SEd Tanous
321f4f2643aSPatrick Williams```cpp
322d02420b2SEd Tanousvoid getMembers(crow::Response& res){
323d02420b2SEd Tanous  res.jsonValue["Value"] = 2;
324d02420b2SEd Tanous}
325d02420b2SEd Tanous```
326d02420b2SEd Tanous
327d02420b2SEd TanousAs an added benefit, this code is also more efficient, as it avoids the
328d02420b2SEd Tanousintermediate object construction and the move, and as a result, produces smaller
329d02420b2SEd Tanousbinaries.
330d02420b2SEd Tanous
331d02420b2SEd TanousNote, another form of this error involves calling nlohmann::json::reset(), to
332d02420b2SEd Tanousclear an object that's already been filled in. This has the potential to clear
333d02420b2SEd Tanouscorrect data that was already filled in from other sources.
334445fce0cSEd Tanous
335445fce0cSEd Tanous## 14. Very long lambda callbacks
336445fce0cSEd Tanous
337445fce0cSEd Tanous```cpp
338445fce0cSEd Tanousdbus::utility::getSubTree("/", interfaces,
339445fce0cSEd Tanous                         [asyncResp](boost::system::error_code& ec,
340445fce0cSEd Tanous                                     MapperGetSubTreeResult& res){
341445fce0cSEd Tanous                            <many lines of code>
342445fce0cSEd Tanous                         })
343445fce0cSEd Tanous```
344445fce0cSEd Tanous
345445fce0cSEd TanousInline lambdas, while useful in some contexts, are difficult to read, and have
346445fce0cSEd Tanousinconsistent formatting with tools like clang-format, which causes significant
347445fce0cSEd Tanousproblems in review, and in applying patchsets that might have minor conflicts.
348445fce0cSEd TanousIn addition, because they are declared in a function scope, they are difficult
349445fce0cSEd Tanousto unit test, and produce log messages that are difficult to read given their
350445fce0cSEd Tanousunnamed nature.
351445fce0cSEd Tanous
352445fce0cSEd TanousPrefer to either use std::bind_front, and a normal method to handle the return,
353445fce0cSEd Tanousor a lambda that is less than 10 lines of code to handle an error inline. In
354445fce0cSEd Tanouscases where std::bind_front cannot be used, such as in
355445fce0cSEd Tanoussdbusplus::asio::connection::async_method_call, keep the lambda length less than
356445fce0cSEd Tanous10 lines, and call the appropriate function for handling non-trivial transforms.
357445fce0cSEd Tanous
358445fce0cSEd Tanous```cpp
359445fce0cSEd Tanousvoid afterGetSubTree(std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
360445fce0cSEd Tanous                     boost::system::error_code& ec,
361445fce0cSEd Tanous                     MapperGetSubTreeResult& res){
362445fce0cSEd Tanous   <many lines of code>
363445fce0cSEd Tanous}
364445fce0cSEd Tanous
365445fce0cSEd Tanousdbus::utility::getSubTree("/xyz/openbmc_project/inventory", interfaces,
366445fce0cSEd Tanous                         std::bind_front(afterGetSubTree, asyncResp));
367445fce0cSEd Tanous```
368445fce0cSEd Tanous
369445fce0cSEd TanousSee also the
370445fce0cSEd Tanous[Cpp Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f11-use-an-unnamed-lambda-if-you-need-a-simple-function-object-in-one-place-only)
371445fce0cSEd Tanousfor generalized guidelines on when lambdas are appropriate. The above
372445fce0cSEd Tanousrecommendation is aligned with the C++ Core Guidelines.
373*9e2d2033Srohitpai
374*9e2d2033Srohitpai## 15. Using async_method_call where there are existing helper methods
375*9e2d2033Srohitpai
376*9e2d2033Srohitpai```cpp
377*9e2d2033Srohitpaicrow::connections::systemBus->async_method_call(
378*9e2d2033Srohitpai    respHandler, "xyz.openbmc_project.ObjectMapper",
379*9e2d2033Srohitpai    "/xyz/openbmc_project/object_mapper",
380*9e2d2033Srohitpai    "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
381*9e2d2033Srohitpai    "/xyz/openbmc_project/inventory", 0, interfaces);
382*9e2d2033Srohitpai```
383*9e2d2033Srohitpai
384*9e2d2033SrohitpaiIt's required to use D-Bus utility functions provided in the file
385*9e2d2033Srohitpaiinclude/dbus_utility.hpp instead of invoking them directly. Using the existing
386*9e2d2033Srohitpaiutil functions will help to reduce the compilation time, increase code reuse and
387*9e2d2033Srohitpaiuniformity in error handling. Below are the list of existing D-Bus utility
388*9e2d2033Srohitpaifunctions
389*9e2d2033Srohitpai
390*9e2d2033Srohitpai- getProperty
391*9e2d2033Srohitpai- getAllProperties
392*9e2d2033Srohitpai- checkDbusPathExists
393*9e2d2033Srohitpai- getSubTree
394*9e2d2033Srohitpai- getSubTreePaths
395*9e2d2033Srohitpai- getAssociatedSubTree
396*9e2d2033Srohitpai- getAssociatedSubTreePaths
397*9e2d2033Srohitpai- getAssociatedSubTreeById
398*9e2d2033Srohitpai- getAssociatedSubTreePathsById
399*9e2d2033Srohitpai- getDbusObject
400*9e2d2033Srohitpai- getAssociationEndPoints
401*9e2d2033Srohitpai- getManagedObjects
402*9e2d2033Srohitpai
403*9e2d2033Srohitpai## 16. Using strings for DMTF schema Enums
404*9e2d2033Srohitpai
405*9e2d2033Srohitpai```cpp
406*9e2d2033SrohitpaisensorJson["ReadingType"] = "Frequency";
407*9e2d2033Srohitpai
408*9e2d2033Srohitpai```
409*9e2d2033Srohitpai
410*9e2d2033SrohitpaiRedfish Schema Enums and types are auto generated using
411*9e2d2033Srohitpaiscripts/generate_schema_enums.py. The generated header files contain the redfish
412*9e2d2033Srohitpaienumerations which must be used for JSON response population.
413*9e2d2033Srohitpai
414*9e2d2033Srohitpai```cpp
415*9e2d2033Srohitpai#include "generated/enums/sensor.hpp"
416*9e2d2033SrohitpaisensorJson["ReadingType"] = sensor::ReadingType::Frequency;
417*9e2d2033Srohitpai```
418