PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/wired-1.3.2/libwired/libwired/misc/wi-error.c

https://bitbucket.org/balrog/zanka-full
C | 410 lines | 231 code | 129 blank | 50 comment | 9 complexity | 9782f31d081c933819c577febebeaf8b MD5 | raw file
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2003-2007 Axel Andersson
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  24. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include "config.h"
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netdb.h>
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <regex.h>
  34. #ifdef WI_CRYPTO
  35. #include <openssl/err.h>
  36. #endif
  37. #ifdef WI_SSL
  38. #include <openssl/ssl.h>
  39. #endif
  40. #ifdef WI_LIBXML2
  41. #include <libxml/xmlerror.h>
  42. #endif
  43. #ifdef WI_ZLIB
  44. #include <zlib.h>
  45. #endif
  46. #include <wired/wi-assert.h>
  47. #include <wired/wi-error.h>
  48. #include <wired/wi-hash.h>
  49. #include <wired/wi-private.h>
  50. #include <wired/wi-runtime.h>
  51. #include <wired/wi-string.h>
  52. #include <wired/wi-thread.h>
  53. #define _WI_ERROR_THREAD_KEY "_wi_error_t"
  54. struct _wi_error {
  55. wi_runtime_base_t base;
  56. wi_string_t *string;
  57. wi_error_domain_t domain;
  58. wi_integer_t code;
  59. };
  60. static wi_error_t * _wi_error_alloc(void);
  61. static wi_error_t * _wi_error_init(wi_error_t *);
  62. static void _wi_error_dealloc(wi_runtime_instance_t *);
  63. static wi_error_t * _wi_get_error(void);
  64. static const char *_wi_error_strings[] = {
  65. /* WI_ERROR_NONE */
  66. "No error",
  67. /* WI_ERROR_ADDRESS_NOAVAILABLEADDRESSES */
  68. "No available addresses",
  69. /* WI_ERROR_HOST_NOAVAILABLEADDRESSES */
  70. "No available addresses",
  71. /* WI_ERROR_LOG_NOSUCHFACILITY */
  72. "No such syslog facility",
  73. /* WI_ERROR_P7_INVALIDSPEC */
  74. "Invalid specification",
  75. /* WI_ERROR_P7_INVALIDMESSAGE */
  76. "Invalid message",
  77. /* WI_ERROR_P7_UNKNOWNMESSAGE */
  78. "Unknown message",
  79. /* WI_ERROR_P7_UNKNOWNFIELD */
  80. "Unknown field",
  81. /* WI_ERROR_P7_HANDSHAKEFAILED */
  82. "Handshake failed",
  83. /* WI_ERROR_P7_CHECKSUMMISMATCH */
  84. "Checksum mismatch",
  85. /* WI_ERROR_REGEXP_NOSLASH */
  86. "Missing \"/\"",
  87. /* WI_ERROR_REGEXP_INVALIDOPTION */
  88. "Invalid option",
  89. /* WI_ERROR_SETTINGS_SYNTAXERROR */
  90. "Syntax error",
  91. /* WI_ERROR_SETTINGS_UNKNOWNSETTING */
  92. "Unknown setting name",
  93. /* WI_ERROR_SETTINGS_NOSUCHUSER */
  94. "User not found",
  95. /* WI_ERROR_SETTINGS_NOSUCHGROUP */
  96. "Group not found",
  97. /* WI_ERROR_SETTINGS_INVALIDPORT */
  98. "Port is not in 1-65535 range",
  99. /* WI_ERROR_SETTINGS_NOSUCHSERVICE */
  100. "Service not found",
  101. /* WI_ERROR_SOCKET_NOVALIDCIPHER */
  102. "No valid cipher",
  103. /* WI_ERROR_SOCKET_NOSSL */
  104. "Socket has no SSL support",
  105. /* WI_ERROR_SOCKET_EOF */
  106. "End of file",
  107. /* WI_ERROR_TERMCAP_NOSUCHENTRY */
  108. "No such entry in termcap database",
  109. /* WI_ERROR_TERMCAP_TERMINFONOTFOUND */
  110. "Termcap databse not found",
  111. /* WI_ERROR_THREADS_NOTSUPP */
  112. "Threads are not supported in this build",
  113. };
  114. static wi_runtime_id_t _wi_error_runtime_id = WI_RUNTIME_ID_NULL;
  115. static wi_runtime_class_t _wi_error_runtime_class = {
  116. "wi_error_t",
  117. _wi_error_dealloc,
  118. NULL,
  119. NULL,
  120. NULL,
  121. NULL
  122. };
  123. void wi_error_register(void) {
  124. _wi_error_runtime_id = wi_runtime_register_class(&_wi_error_runtime_class);
  125. }
  126. void wi_error_initialize(void) {
  127. #ifdef WI_SSL
  128. SSL_load_error_strings();
  129. #endif
  130. #ifdef WI_CRYPTO
  131. ERR_load_crypto_strings();
  132. #endif
  133. }
  134. #pragma mark -
  135. static wi_error_t * _wi_error_alloc(void) {
  136. return wi_runtime_create_instance(_wi_error_runtime_id, sizeof(wi_error_t));
  137. }
  138. static wi_error_t * _wi_error_init(wi_error_t *error) {
  139. return error;
  140. }
  141. static void _wi_error_dealloc(wi_runtime_instance_t *instance) {
  142. wi_error_t *error = instance;
  143. wi_release(error->string);
  144. }
  145. #pragma mark -
  146. static wi_error_t * _wi_get_error(void) {
  147. wi_error_t *error;
  148. error = wi_hash_data_for_key(wi_thread_hash(), WI_STR(_WI_ERROR_THREAD_KEY));
  149. WI_ASSERT(error != NULL, "no wi_error_t created for thread", 0);
  150. return error;
  151. }
  152. #pragma mark -
  153. void wi_error_enter_thread(void) {
  154. wi_error_t *error;
  155. error = _wi_error_init(_wi_error_alloc());
  156. wi_hash_set_data_for_key(wi_thread_hash(), error, WI_STR(_WI_ERROR_THREAD_KEY));
  157. wi_release(error);
  158. wi_error_set_error(WI_ERROR_DOMAIN_NONE, WI_ERROR_NONE);
  159. }
  160. void wi_error_set_error(wi_error_domain_t domain, int code) {
  161. wi_error_t *error;
  162. error = _wi_get_error();
  163. error->domain = domain;
  164. error->code = code;
  165. wi_release(error->string);
  166. error->string = NULL;
  167. }
  168. void wi_error_set_errno(int code) {
  169. wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, code);
  170. }
  171. #if defined(WI_CRYPTO) || defined(WI_SSL)
  172. void wi_error_set_openssl_error(void) {
  173. wi_error_t *error;
  174. const char *file;
  175. int line;
  176. if(ERR_peek_error() == 0) {
  177. wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
  178. } else {
  179. error = _wi_get_error();
  180. error->domain = WI_ERROR_DOMAIN_OPENSSL;
  181. error->code = ERR_get_error_line(&file, &line);
  182. wi_release(error->string);
  183. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s:%d: %s: %s (%u)"),
  184. file,
  185. line,
  186. ERR_func_error_string(error->code),
  187. ERR_reason_error_string(error->code),
  188. ERR_GET_REASON(error->code));
  189. }
  190. }
  191. #endif
  192. #ifdef WI_LIBXML2
  193. void wi_error_set_libxml2_error(void) {
  194. wi_error_t *error;
  195. xmlErrorPtr xml_error;
  196. xml_error = xmlGetLastError();
  197. error = _wi_get_error();
  198. error->domain = WI_ERROR_DOMAIN_REGEX;
  199. error->code = xml_error->code;
  200. wi_release(error->string);
  201. error->string = wi_string_init_with_cstring(wi_string_alloc(), xml_error->message);
  202. wi_string_delete_surrounding_whitespace(error->string);
  203. }
  204. #endif
  205. void wi_error_set_regex_error(regex_t *regex, int code) {
  206. wi_error_t *error;
  207. char string[256];
  208. error = _wi_get_error();
  209. error->domain = WI_ERROR_DOMAIN_REGEX;
  210. error->code = code;
  211. wi_release(error->string);
  212. regerror(code, regex, string, sizeof(string));
  213. error->string = wi_string_init_with_cstring(wi_string_alloc(), string);
  214. }
  215. #ifdef WI_ZLIB
  216. void wi_error_set_zlib_error(int code) {
  217. if(code == Z_ERRNO)
  218. wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
  219. else
  220. wi_error_set_error(WI_ERROR_DOMAIN_ZLIB, code);
  221. }
  222. #endif
  223. void wi_error_set_libwired_error(int code) {
  224. wi_error_set_error(WI_ERROR_DOMAIN_LIBWIRED, code);
  225. }
  226. void wi_error_set_libwired_p7_error(int code, wi_string_t *fmt, ...) {
  227. wi_error_t *error;
  228. va_list ap;
  229. error = _wi_get_error();
  230. error->domain = WI_ERROR_DOMAIN_LIBWIRED;
  231. error->code = code;
  232. wi_release(error->string);
  233. error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
  234. if(wi_string_length(fmt) > 0) {
  235. wi_string_append_string(error->string, WI_STR(": "));
  236. va_start(ap, fmt);
  237. wi_string_append_format_and_arguments(error->string, fmt, ap);
  238. va_end(ap);
  239. }
  240. }
  241. #pragma mark -
  242. wi_string_t * wi_error_string(void) {
  243. wi_error_t *error;
  244. error = _wi_get_error();
  245. if(!error->string) {
  246. switch(error->domain) {
  247. case WI_ERROR_DOMAIN_ERRNO:
  248. error->string = wi_string_init_with_cstring(wi_string_alloc(), strerror(error->code));
  249. break;
  250. case WI_ERROR_DOMAIN_GAI:
  251. error->string = wi_string_init_with_cstring(wi_string_alloc(), gai_strerror(error->code));
  252. break;
  253. case WI_ERROR_DOMAIN_REGEX:
  254. break;
  255. case WI_ERROR_DOMAIN_OPENSSL:
  256. break;
  257. case WI_ERROR_DOMAIN_LIBXML2:
  258. break;
  259. case WI_ERROR_DOMAIN_ZLIB:
  260. #ifdef WI_ZLIB
  261. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("zlib: %s"), zError(error->code));
  262. #endif
  263. break;
  264. case WI_ERROR_DOMAIN_NONE:
  265. case WI_ERROR_DOMAIN_LIBWIRED:
  266. error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
  267. break;
  268. }
  269. }
  270. return error->string;
  271. }
  272. wi_error_domain_t wi_error_domain(void) {
  273. wi_error_t *error;
  274. error = _wi_get_error();
  275. return error->domain;
  276. }
  277. wi_integer_t wi_error_code(void) {
  278. wi_error_t *error;
  279. error = _wi_get_error();
  280. return error->code;
  281. }