exception.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /////////////////////////////////////////////////////////////////////////////
  2. /// @file exception.h
  3. /// Declaration of MQTT exception class
  4. /// @date May 1, 2013
  5. /// @author Frank Pagliughi
  6. /////////////////////////////////////////////////////////////////////////////
  7. /*******************************************************************************
  8. * Copyright (c) 2013-2024 Frank Pagliughi <fpagliughi@mindspring.com>
  9. *
  10. * All rights reserved. This program and the accompanying materials
  11. * are made available under the terms of the Eclipse Public License v2.0
  12. * and Eclipse Distribution License v1.0 which accompany this distribution.
  13. *
  14. * The Eclipse Public License is available at
  15. * http://www.eclipse.org/legal/epl-v20.html
  16. * and the Eclipse Distribution License is available at
  17. * http://www.eclipse.org/org/documents/edl-v10.php.
  18. *
  19. * Contributors:
  20. * Frank Pagliughi - initial implementation and documentation
  21. *******************************************************************************/
  22. #ifndef __mqtt_exception_h
  23. #define __mqtt_exception_h
  24. #include <exception>
  25. #include <iostream>
  26. #include <memory>
  27. #include <stdexcept>
  28. #include <vector>
  29. #include "MQTTAsync.h"
  30. #include "mqtt/types.h"
  31. namespace mqtt {
  32. /** Bring std::bad_cast into the mqtt namespace */
  33. using bad_cast = std::bad_cast;
  34. /////////////////////////////////////////////////////////////////////////////
  35. /**
  36. * Base mqtt::exception.
  37. * This wraps the error codes which originate from the underlying C library.
  38. */
  39. class exception : public std::runtime_error
  40. {
  41. protected:
  42. /** The error return code from the C library */
  43. int rc_;
  44. /** The reason code from the server */
  45. ReasonCode reasonCode_;
  46. /** The error message from the C library */
  47. string msg_;
  48. /** See if the return code is actually a reason code error value */
  49. static ReasonCode reason_code(int rc, ReasonCode reasonCode) {
  50. if (reasonCode == ReasonCode::SUCCESS && rc >= ReasonCode::UNSPECIFIED_ERROR)
  51. reasonCode = ReasonCode(rc);
  52. return reasonCode;
  53. }
  54. public:
  55. /**
  56. * Creates an MQTT exception.
  57. * @param rc The error return code from the C library.
  58. */
  59. explicit exception(int rc) : exception(rc, error_str(rc)) {}
  60. /**
  61. * Creates an MQTT exception.
  62. * @param rc The error return code from the C library.
  63. * @param reasonCode The reason code from the server response.
  64. */
  65. explicit exception(int rc, ReasonCode reasonCode)
  66. : exception(rc, reasonCode, error_str(rc)) {}
  67. /**
  68. * Creates an MQTT exception.
  69. * @param rc The error return code from the C library.
  70. * @param msg The text message for the error.
  71. */
  72. exception(int rc, const string& msg) : exception(rc, ReasonCode::SUCCESS, msg) {}
  73. /**
  74. * Creates an MQTT exception.
  75. * @param rc The error return code from the C library.
  76. * @param reasonCode The reason code from the server
  77. * @param msg The text message for the error.
  78. */
  79. exception(int rc, ReasonCode reasonCode, const string& msg)
  80. : std::runtime_error(printable_error(rc, reasonCode, msg)),
  81. rc_{rc},
  82. reasonCode_{reason_code(rc, reasonCode)},
  83. msg_{msg} {}
  84. /**
  85. * Gets an error message from an error code.
  86. * @param rc The error code from the C lib
  87. * @return A string explanation of the error
  88. */
  89. static string error_str(int rc) {
  90. const char* msg = ::MQTTAsync_strerror(rc);
  91. return msg ? string(msg) : string();
  92. }
  93. /**
  94. * Gets a string describing the MQTT v5 reason code.
  95. * @param reasonCode The MQTT v5 reason code.
  96. * @return A string describing the reason code.
  97. */
  98. static string reason_code_str(int reasonCode) {
  99. auto msg = ::MQTTReasonCode_toString(MQTTReasonCodes(reasonCode));
  100. return (msg) ? string{msg} : string{};
  101. }
  102. /**
  103. * Gets a detailed error message for an error code.
  104. * @param rc The error code from the C lib
  105. * @param reasonCode The MQTT v5 reason code
  106. * @param msg An optional additional message. If none is provided, the
  107. * error_str message is used.
  108. * @return A string error message that includes the error code and an
  109. * explanation message.
  110. */
  111. static string printable_error(
  112. int rc, ReasonCode reasonCode = ReasonCode::SUCCESS, const string& msg = string()
  113. ) {
  114. reasonCode = reason_code(rc, reasonCode);
  115. string s = "MQTT error [" + std::to_string(rc) + "]";
  116. if (!msg.empty())
  117. s += string(": ") + msg;
  118. if (reasonCode != ReasonCode::SUCCESS)
  119. s += string(". ") + reason_code_str(reasonCode);
  120. return s;
  121. }
  122. /**
  123. * Returns the return code for this exception.
  124. */
  125. int get_return_code() const { return rc_; }
  126. /**
  127. * Gets a string of the error code.
  128. * @return A string of the error code.
  129. */
  130. string get_error_str() const { return error_str(rc_); }
  131. /**
  132. * Returns the reason code for this exception.
  133. * For MQTT v3 connections, this is actually the return code.
  134. */
  135. int get_reason_code() const { return reasonCode_; }
  136. /**
  137. * Gets a string for the reason code.
  138. * @return A string for the reason code.
  139. */
  140. string get_reason_code_str() const { return reason_code_str(reasonCode_); }
  141. /**
  142. * Returns the error message for this exception.
  143. */
  144. string get_message() const { return msg_; }
  145. /**
  146. * Gets a string representation of this exception.
  147. * @return A string representation of this exception.
  148. */
  149. string to_string() const { return string(what()); }
  150. };
  151. /**
  152. * Stream inserter writes a fairly verbose message
  153. * @param os The stream.
  154. * @param exc The exception to write.
  155. * @return A reference to the stream.
  156. */
  157. inline std::ostream& operator<<(std::ostream& os, const exception& exc) {
  158. os << exc.what();
  159. return os;
  160. }
  161. /////////////////////////////////////////////////////////////////////////////
  162. /**
  163. * Exception thrown when an expected server response is missing.
  164. */
  165. class missing_response : public exception
  166. {
  167. public:
  168. /**
  169. * Create a missing response error.
  170. * @param rsp A string for the type of response expected.
  171. */
  172. missing_response(const string& rsp)
  173. : exception(MQTTASYNC_FAILURE, "Missing " + rsp + " response") {}
  174. };
  175. /////////////////////////////////////////////////////////////////////////////
  176. /**
  177. * A timeout exception, particularly from the synchronous client.
  178. */
  179. class timeout_error : public exception
  180. {
  181. public:
  182. /**
  183. * Create a timeout error.
  184. */
  185. timeout_error() : exception(MQTTASYNC_FAILURE, "Timeout") {}
  186. };
  187. /////////////////////////////////////////////////////////////////////////////
  188. /**
  189. * This exception is thrown by the implementor of the persistence interface
  190. * if there is a problem reading or writing persistent data.
  191. */
  192. class persistence_exception : public exception
  193. {
  194. public:
  195. /**
  196. * Creates an MQTT persistence exception.
  197. */
  198. persistence_exception() : exception(MQTTCLIENT_PERSISTENCE_ERROR) {}
  199. /**
  200. * Creates an MQTT persistence exception.
  201. * @param code The error code from the C library.
  202. */
  203. explicit persistence_exception(int code) : exception(code) {}
  204. /**
  205. * Creates an MQTT persistence exception.
  206. * @param msg The text message for the error.
  207. */
  208. explicit persistence_exception(const string& msg)
  209. : exception(MQTTCLIENT_PERSISTENCE_ERROR, msg) {}
  210. /**
  211. * Creates an MQTT persistence exception.
  212. * @param code The error code
  213. * @param msg The text message for the error.
  214. */
  215. persistence_exception(int code, const string& msg) : exception(code, msg) {}
  216. };
  217. /////////////////////////////////////////////////////////////////////////////
  218. /**
  219. * Thrown when a client is not authorized to perform an operation, or if
  220. * there is a problem with the security configuration.
  221. */
  222. class security_exception : public exception
  223. {
  224. public:
  225. /**
  226. * Creates an MQTT security exception
  227. * @param code The error code.
  228. */
  229. explicit security_exception(int code) : exception(code) {}
  230. /**
  231. * Creates an MQTT security exception
  232. * @param code The error code.
  233. * @param msg The text message for the error.
  234. */
  235. security_exception(int code, const string& msg) : exception(code, msg) {}
  236. };
  237. /////////////////////////////////////////////////////////////////////////////
  238. } // namespace mqtt
  239. #endif // __mqtt_exception_h