1 #pragma once
2 
3 #include <systemd/sd-bus.h>
4 
5 #include <sdbusplus/sdbus.hpp>
6 
7 #include <exception>
8 #include <string>
9 
10 namespace sdbusplus
11 {
12 
13 enum class UnpackErrorReason
14 {
15     missingProperty,
16     wrongType
17 };
18 
19 namespace exception
20 {
21 
22 /** Base exception class for all sdbusplus exceptions, including those created
23  *  by the bindings. */
24 struct exception : public std::exception
25 {
26     virtual const char* name() const noexcept = 0;
27     virtual const char* description() const noexcept = 0;
28     virtual int get_errno() const noexcept = 0;
29 
30   private:
31     // This unused function is to ensure that the vtable for this class is
32     // properly emitted when `-flto=auto` is used, which is the default in
33     // Yocto builds.  Without this, the vtable is a hidden symbol and no
34     // users can inherit from our exception type directly.
35     virtual void unused() const noexcept;
36 };
37 
38 /** base exception class for all errors created by the sdbus++ generator */
39 struct generated_exception : public exception
40 {
41     int get_errno() const noexcept override;
42 };
43 
44 /** base exception class for all errors generated by sdbusplus itself. */
45 struct internal_exception : public exception
46 {};
47 
48 /** Exception for when an underlying sd_bus method call fails. */
49 class SdBusError final : public internal_exception
50 {
51   public:
52     /** Errno must be positive */
53     SdBusError(int error, const char* prefix,
54                SdBusInterface* intf = &sdbus_impl);
55     SdBusError(int error, std::string&& prefix,
56                SdBusInterface* intf = &sdbus_impl);
57     /** Becomes the owner of the error */
58     SdBusError(sd_bus_error* error, const char* prefix,
59                SdBusInterface* intf = &sdbus_impl);
60 
61     SdBusError(const SdBusError&) = delete;
62     SdBusError& operator=(const SdBusError&) = delete;
63     SdBusError(SdBusError&& other);
64     SdBusError& operator=(SdBusError&& other);
65     ~SdBusError() override;
66 
67     const char* name() const noexcept override;
68     const char* description() const noexcept override;
69     const char* what() const noexcept override;
70     int get_errno() const noexcept override;
71     const sd_bus_error* get_error() const noexcept;
72 
73   private:
74     sd_bus_error error;
75     std::string full_message;
76     SdBusInterface* intf;
77 
78     /** Populates the full_message from the stored
79      *  error and the passed in prefix. */
80     void populateMessage(std::string&& prefix);
81 
82     /** Helper to reduce duplicate move logic */
83     void move(SdBusError&& other);
84 };
85 
86 /** Exception for when an invalid conversion from string to enum is
87  *  attempted. */
88 struct InvalidEnumString final : public internal_exception
89 {
90     static constexpr auto errName =
91         "xyz.openbmc_project.sdbusplus.Error.InvalidEnumString";
92     static constexpr auto errDesc =
93         "An enumeration mapping was attempted for which no valid enumeration "
94         "value exists.";
95     static constexpr auto errWhat =
96         "xyz.openbmc_project.sdbusplus.Error.InvalidEnumString: "
97         "An enumeration mapping was attempted for which no valid enumeration "
98         "value exists.";
99 
100     const char* name() const noexcept override;
101     const char* description() const noexcept override;
102     const char* what() const noexcept override;
103     int get_errno() const noexcept override;
104 };
105 
106 /** Exception for when unpackProperties cannot find given property in provided
107  * container */
108 class UnpackPropertyError final : public internal_exception
109 {
110   public:
111     UnpackPropertyError(std::string_view propertyName,
112                         const UnpackErrorReason reason);
113 
114     static constexpr auto errName =
115         "xyz.openbmc_project.sdbusplus.Error.UnpackPropertyError";
116     static constexpr auto errDesc =
117         "unpackProperties failed to unpack one of requested properties.";
118     static constexpr auto errWhat =
119         "xyz.openbmc_project.sdbusplus.Error.UnpackPropertyError: "
120         "unpackProperties failed to unpack one of requested properties.";
121 
122     const char* name() const noexcept override;
123     const char* description() const noexcept override;
124     const char* what() const noexcept override;
125     int get_errno() const noexcept override;
126 
127     const std::string propertyName;
128     const UnpackErrorReason reason;
129 
130   private:
131     const std::string errWhatDetailed;
132 };
133 
134 class UnhandledStop final : public internal_exception
135 {
136   public:
137     static constexpr auto errName =
138         "xyz.openbmc_project.sdbusplus.Error.UnhandledStop";
139     static constexpr auto errDesc =
140         "An async Sender failed to handle a stop condition.";
141     static constexpr auto errWhat =
142         "xyz.openbmc_project.sdbusplus.Error.UnhandledStop: "
143         "An async Sender failed to handle a stop condition.";
144 
145     const char* name() const noexcept override;
146     const char* description() const noexcept override;
147     const char* what() const noexcept override;
148     int get_errno() const noexcept override;
149 };
150 
151 } // namespace exception
152 
153 using exception_t = exception::exception;
154 using internal_exception_t = exception::internal_exception;
155 
156 } // namespace sdbusplus
157