message: Add method_error creation from exception

We currently only support creating methods from a unix errno and
description. This allows us to create error return messages directly
from sdbusplus exceptions that internally provide the required name and
description.

Change-Id: I4db91b191e13ba78e7796312d018d3d08d2c8aed
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/sdbusplus/message.hpp b/include/sdbusplus/message.hpp
index 95d61ec..dafbcfb 100644
--- a/include/sdbusplus/message.hpp
+++ b/include/sdbusplus/message.hpp
@@ -2,6 +2,7 @@
 
 #include <systemd/sd-bus.h>
 
+#include <sdbusplus/exception.hpp>
 #include <sdbusplus/message/append.hpp>
 #include <sdbusplus/message/native_types.hpp>
 #include <sdbusplus/message/read.hpp>
@@ -310,6 +311,24 @@
 
     /** @brief Create a 'method_error' type message from an existing message.
      *
+     *  @param[in] e - The exception we are returning
+     *  @return method-return message.
+     */
+    message new_method_error(const sdbusplus::exception::exception& e)
+    {
+        msgp_t reply = nullptr;
+        int r = _intf->sd_bus_message_new_method_error(
+            this->get(), &reply, e.name(), e.description());
+        if (r < 0)
+        {
+            throw exception::SdBusError(-r, "sd_bus_message_new_method_error");
+        }
+
+        return message(reply, _intf, std::false_type());
+    }
+
+    /** @brief Create a 'method_error' type message from an existing message.
+     *
      *  @param[in] error - integer error number
      *  @param[in] e - optional pointer to preformatted sd_bus_error
      *  @return method-error message.
diff --git a/include/sdbusplus/sdbus.hpp b/include/sdbusplus/sdbus.hpp
index 5a73309..b30e989 100644
--- a/include/sdbusplus/sdbus.hpp
+++ b/include/sdbusplus/sdbus.hpp
@@ -111,6 +111,11 @@
     virtual int sd_bus_message_new_method_return(sd_bus_message* call,
                                                  sd_bus_message** m) = 0;
 
+    virtual int sd_bus_message_new_method_error(sd_bus_message* call,
+                                                sd_bus_message** m,
+                                                const char* name,
+                                                const char* description) = 0;
+
     virtual int sd_bus_message_new_method_errno(sd_bus_message* call,
                                                 sd_bus_message** m, int error,
                                                 const sd_bus_error* p) = 0;
@@ -398,6 +403,14 @@
         return ::sd_bus_message_new_method_return(call, m);
     }
 
+    int sd_bus_message_new_method_error(sd_bus_message* call,
+                                        sd_bus_message** m, const char* name,
+                                        const char* description) override
+    {
+        return ::sd_bus_message_new_method_errorf(call, m, name, "%s",
+                                                  description);
+    }
+
     int sd_bus_message_new_method_errno(sd_bus_message* call,
                                         sd_bus_message** m, int error,
                                         const sd_bus_error* p) override
diff --git a/include/sdbusplus/test/sdbus_mock.hpp b/include/sdbusplus/test/sdbus_mock.hpp
index b88b120..ff007a4 100644
--- a/include/sdbusplus/test/sdbus_mock.hpp
+++ b/include/sdbusplus/test/sdbus_mock.hpp
@@ -85,6 +85,10 @@
     MOCK_METHOD2(sd_bus_message_new_method_return,
                  int(sd_bus_message*, sd_bus_message**));
 
+    MOCK_METHOD4(sd_bus_message_new_method_error,
+                 int(sd_bus_message* call, sd_bus_message** m, const char* name,
+                     const char* description));
+
     MOCK_METHOD4(sd_bus_message_new_method_errno,
                  int(sd_bus_message* call, sd_bus_message** m, int error,
                      const sd_bus_error* p));