bus/call: Implement exception handling on call failures

The benefit of these exceptions over the current message error handling
is that we populate an sd_bus_error struct with the error data from the
sd_bus_call. In the cases where there is an underlying dbus error, we
will get more information from the sd_bus_error that is plumbed through
the exception message.

Tested:
  Built and booted a BMC + Host from a full tray poweroff with no
  failed units.

Change-Id: If55b9e380815bc2ac02eb3683af19a6510c4f4cf
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/sdbusplus/bus.hpp.in b/sdbusplus/bus.hpp.in
index c19c2f5..a0f21ed 100644
--- a/sdbusplus/bus.hpp.in
+++ b/sdbusplus/bus.hpp.in
@@ -7,6 +7,7 @@
 #include <string>
 #include <systemd/sd-bus.h>
 #include <systemd/sd-event.h>
+#include <sdbusplus/exception.hpp>
 #include <sdbusplus/message.hpp>
 #include <sdbusplus/sdbus.hpp>
 
@@ -226,8 +227,14 @@
      */
     auto call(message::message& m, uint64_t timeout_us = 0)
     {
+        sd_bus_error error = SD_BUS_ERROR_NULL;
         sd_bus_message* reply = nullptr;
-        _intf->sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, &reply);
+        int r = _intf->sd_bus_call(_bus.get(), m.get(), timeout_us, &error,
+                                   &reply);
+        if (r < 0)
+        {
+            throw exception::SdBusError(error, "sd_bus_call");
+        }
 
         return message::message(reply, _intf, std::false_type());
     }
@@ -239,7 +246,13 @@
      */
     void call_noreply(message::message& m, uint64_t timeout_us = 0)
     {
-        _intf->sd_bus_call(_bus.get(), m.get(), timeout_us, nullptr, nullptr);
+        sd_bus_error error = SD_BUS_ERROR_NULL;
+        int r = _intf->sd_bus_call(_bus.get(), m.get(), timeout_us, &error,
+                                   nullptr);
+        if (r < 0)
+        {
+            throw exception::SdBusError(error, "sd_bus_call noreply");
+        }
     }
 
     /** @brief Get the bus unique name. Ex: ":1.11".