exception.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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-2019 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 "MQTTAsync.h"
  25. #include "mqtt/types.h"
  26. #include <iostream>
  27. #include <vector>
  28. #include <memory>
  29. #include <exception>
  30. #include <stdexcept>
  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. public:
  49. /**
  50. * Creates an MQTT exception.
  51. * @param rc The error return code from the C library.
  52. */
  53. explicit exception(int rc)
  54. : exception(rc, error_str(rc)) {}
  55. /**
  56. * Creates an MQTT exception.
  57. * @param rc The error return code from the C library.
  58. * @param reasonCode The reason code from the server response.
  59. */
  60. explicit exception(int rc, ReasonCode reasonCode)
  61. : exception(rc, reasonCode, error_str(rc)) {}
  62. /**
  63. * Creates an MQTT exception.
  64. * @param rc The error return code from the C library.
  65. * @param msg The text message for the error.
  66. */
  67. exception(int rc, const string& msg)
  68. : std::runtime_error(printable_error(rc, ReasonCode::SUCCESS, msg)),
  69. rc_(rc), reasonCode_(ReasonCode::SUCCESS), msg_(msg) {}
  70. /**
  71. * Creates an MQTT exception.
  72. * @param rc The error return code from the C library.
  73. * @param reasonCode The reason code from the server
  74. * @param msg The text message for the error.
  75. */
  76. exception(int rc, ReasonCode reasonCode, const string& msg)
  77. : std::runtime_error(printable_error(rc, reasonCode, msg)),
  78. rc_(rc), reasonCode_(reasonCode), msg_(msg) {}
  79. /**
  80. * Gets an error message from an error code.
  81. * @param rc The error code from the C lib
  82. * @return A string explanation of the error
  83. */
  84. static string error_str(int rc) {
  85. const char *msg = ::MQTTAsync_strerror(rc);
  86. return msg ? string(msg) : string();
  87. }
  88. /**
  89. * Gets a string describing the MQTT v5 reason code.
  90. * @param reasonCode The MQTT v5 reason code.
  91. * @return A string describing the reason code.
  92. */
  93. static string reason_code_str(int reasonCode) {
  94. if (reasonCode != MQTTPP_V3_CODE) {
  95. auto msg = ::MQTTReasonCode_toString(MQTTReasonCodes(reasonCode));
  96. if (msg) return string(msg);
  97. }
  98. return string();
  99. }
  100. /**
  101. * Gets a detailed error message for an error code.
  102. * @param rc The error code from the C lib
  103. * @param reasonCode The MQTT v5 reason code
  104. * @param msg An optional additional message. If none is provided, the
  105. * error_str message is used.
  106. * @return A string error message that includes the error code and an
  107. * explanation message.
  108. */
  109. static string printable_error(int rc, int reasonCode=ReasonCode::SUCCESS,
  110. const string& msg=string()) {
  111. string s = "MQTT error [" + std::to_string(rc) + "]";
  112. if (!msg.empty())
  113. s += string(": ") + msg;
  114. if (reasonCode != MQTTPP_V3_CODE && reasonCode != ReasonCode::SUCCESS)
  115. s += string(". Reason: ") + reason_code_str(reasonCode);
  116. return s;
  117. }
  118. /**
  119. * Returns the return code for this exception.
  120. */
  121. int get_return_code() const { return rc_; }
  122. /**
  123. * Gets a string of the error code.
  124. * @return A string of the error code.
  125. */
  126. string get_error_str() const { return error_str(rc_); }
  127. /**
  128. * Returns the reason code for this exception.
  129. * For MQTT v3 connections, this is actually the return code.
  130. */
  131. int get_reason_code() const {
  132. return reasonCode_ == MQTTPP_V3_CODE ? rc_ : reasonCode_;
  133. }
  134. /**
  135. * Gets a string for the reason code.
  136. * @return A string for the reason code.
  137. */
  138. string get_reason_code_str() const {
  139. return reason_code_str(reasonCode_);
  140. }
  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)
  216. : exception(code, msg) {}
  217. };
  218. /////////////////////////////////////////////////////////////////////////////
  219. /**
  220. * Thrown when a client is not authorized to perform an operation, or if
  221. * there is a problem with the security configuration.
  222. */
  223. class security_exception : public exception
  224. {
  225. public:
  226. /**
  227. * Creates an MQTT security exception
  228. * @param code The error code.
  229. */
  230. explicit security_exception(int code) : exception(code) {}
  231. /**
  232. * Creates an MQTT security exception
  233. * @param code The error code.
  234. * @param msg The text message for the error.
  235. */
  236. security_exception(int code, const string& msg) : exception(code, msg) {}
  237. };
  238. /////////////////////////////////////////////////////////////////////////////
  239. // end namespace mqtt
  240. }
  241. #endif // __mqtt_token_h