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