PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/balrog/zanka-full
C | 598 lines | 353 code | 180 blank | 65 comment | 20 complexity | 434d6c9cc3dfae551348c8612d7bf335 MD5 | raw file
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2003-2009 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 HAVE_OPENSSL_SHA_H
  35. #include <openssl/err.h>
  36. #endif
  37. #ifdef HAVE_OPENSSL_SSL_H
  38. #include <openssl/ssl.h>
  39. #endif
  40. #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
  41. #include <CommonCrypto/CommonCryptor.h>
  42. #endif
  43. #ifdef HAVE_LIBXML_PARSER_H
  44. #include <libxml/xmlerror.h>
  45. #endif
  46. #ifdef HAVE_ZLIB_H
  47. #include <zlib.h>
  48. #endif
  49. #include <wired/wi-assert.h>
  50. #include <wired/wi-dictionary.h>
  51. #include <wired/wi-error.h>
  52. #include <wired/wi-private.h>
  53. #include <wired/wi-runtime.h>
  54. #include <wired/wi-string.h>
  55. #include <wired/wi-thread.h>
  56. #define _WI_ERROR_THREAD_KEY "_wi_error_t"
  57. struct _wi_error {
  58. wi_runtime_base_t base;
  59. wi_string_t *string;
  60. wi_error_domain_t domain;
  61. wi_integer_t code;
  62. };
  63. static wi_error_t * _wi_error_alloc(void);
  64. static wi_error_t * _wi_error_init(wi_error_t *);
  65. static void _wi_error_dealloc(wi_runtime_instance_t *);
  66. static wi_error_t * _wi_error_get_error(void);
  67. #ifdef HAVE_LIBXML_PARSER_H
  68. static void _wi_error_xml_error_handler(void *, const char *, ...);
  69. #endif
  70. static const char *_wi_error_strings[] = {
  71. /* WI_ERROR_NONE */
  72. "No error",
  73. /* WI_ERROR_ADDRESS_NOAVAILABLEADDRESSES */
  74. "No available addresses",
  75. /* WI_ERROR_CIPHER_CIPHERNOTSUPP */
  76. "Cipher not supported",
  77. /* WI_ERROR_FILE_NOCARBON */
  78. "Carbon not supported",
  79. /* WI_ERROR_FSEVENTS_NOTSUPP */
  80. "No compatible API available",
  81. /* WI_ERROR_HOST_NOAVAILABLEADDRESSES */
  82. "No available addresses",
  83. /* WI_ERROR_LOG_NOSUCHFACILITY */
  84. "No such syslog facility",
  85. /* WI_ERROR_P7_INVALIDSPEC */
  86. "Invalid specification",
  87. /* WI_ERROR_P7_INVALIDMESSAGE */
  88. "Invalid message",
  89. /* WI_ERROR_P7_UNKNOWNMESSAGE */
  90. "Unknown message",
  91. /* WI_ERROR_P7_UNKNOWNFIELD */
  92. "Unknown field",
  93. /* WI_ERROR_P7_HANDSHAKEFAILED */
  94. "Handshake failed",
  95. /* WI_ERROR_P7_INCOMPATIBLE_SPEC */
  96. "",
  97. /* WI_ERROR_P7_AUTHENTICATIONFAILED */
  98. "Authentication failed",
  99. /* WI_ERROR_P7_CHECKSUMMISMATCH */
  100. "Checksum mismatch",
  101. /* WI_ERROR_P7_NORSAKEY */
  102. "No private RSA key set",
  103. /* WI_ERROR_P7_MESSAGETOOLARGE */
  104. "Message too large",
  105. /* WI_ERROR_P7_RSANOTSUPP */
  106. "RSA not supported",
  107. /* WI_ERROR_PLIST_READFAILED */
  108. "Property list read failed",
  109. /* WI_ERROR_PLIST_WRITEFAILED */
  110. "Property list write failed",
  111. /* WI_ERROR_REGEXP_NOSLASH */
  112. "Missing \"/\"",
  113. /* WI_ERROR_REGEXP_INVALIDOPTION */
  114. "Invalid option",
  115. /* WI_ERROR_SETTINGS_SYNTAXERROR */
  116. "Syntax error",
  117. /* WI_ERROR_SETTINGS_UNKNOWNSETTING */
  118. "Unknown setting name",
  119. /* WI_ERROR_SETTINGS_NOSUCHUSER */
  120. "User not found",
  121. /* WI_ERROR_SETTINGS_NOSUCHGROUP */
  122. "Group not found",
  123. /* WI_ERROR_SETTINGS_INVALIDPORT */
  124. "Port is not in 1-65535 range",
  125. /* WI_ERROR_SETTINGS_NOSUCHSERVICE */
  126. "Service not found",
  127. /* WI_ERROR_SOCKET_NOVALIDCIPHER */
  128. "No valid cipher",
  129. /* WI_ERROR_SOCKET_EOF */
  130. "End of file",
  131. /* WI_ERROR_SSL_ERROR_NONE */
  132. "OpenSSL: No error",
  133. /* WI_ERROR_SSL_ERROR_ZERO_RETURN */
  134. "OpenSSL: Zero return",
  135. /* WI_ERROR_SSL_ERROR_WANT_READ */
  136. "OpenSSL: Want read",
  137. /* WI_ERROR_SSL_ERROR_WANT_WRITE */
  138. "OpenSSL: Want write",
  139. /* WI_ERROR_SSL_ERROR_WANT_CONNECT */
  140. "OpenSSL: Want connect",
  141. /* WI_ERROR_SSL_ERROR_WANT_ACCEPT */
  142. "OpenSSL: Want accept",
  143. /* WI_ERROR_SSL_ERROR_WANT_X509_LOOKUP */
  144. "OpenSSL: Want X509 lookup",
  145. /* WI_ERROR_TERMCAP_NOSUCHENTRY */
  146. "No such entry in termcap database",
  147. /* WI_ERROR_TERMCAP_TERMINFONOTFOUND */
  148. "Termcap databse not found",
  149. };
  150. static wi_runtime_id_t _wi_error_runtime_id = WI_RUNTIME_ID_NULL;
  151. static wi_runtime_class_t _wi_error_runtime_class = {
  152. "wi_error_t",
  153. _wi_error_dealloc,
  154. NULL,
  155. NULL,
  156. NULL,
  157. NULL
  158. };
  159. void wi_error_register(void) {
  160. _wi_error_runtime_id = wi_runtime_register_class(&_wi_error_runtime_class);
  161. }
  162. void wi_error_initialize(void) {
  163. #ifdef HAVE_OPENSSL_SSL_H
  164. SSL_load_error_strings();
  165. #endif
  166. #ifdef HAVE_OPENSSL_SHA_H
  167. ERR_load_crypto_strings();
  168. #endif
  169. }
  170. #pragma mark -
  171. static wi_error_t * _wi_error_alloc(void) {
  172. return wi_runtime_create_instance(_wi_error_runtime_id, sizeof(wi_error_t));
  173. }
  174. static wi_error_t * _wi_error_init(wi_error_t *error) {
  175. return error;
  176. }
  177. static void _wi_error_dealloc(wi_runtime_instance_t *instance) {
  178. wi_error_t *error = instance;
  179. wi_release(error->string);
  180. }
  181. #pragma mark -
  182. static wi_error_t * _wi_error_get_error(void) {
  183. wi_error_t *error;
  184. error = wi_dictionary_data_for_key(wi_thread_dictionary(), WI_STR(_WI_ERROR_THREAD_KEY));
  185. WI_ASSERT(error != NULL, "no wi_error_t created for thread", 0);
  186. return error;
  187. }
  188. #ifdef HAVE_LIBXML_PARSER_H
  189. static void _wi_error_xml_error_handler(void *context, const char *message, ...) {
  190. }
  191. #endif
  192. #pragma mark -
  193. void wi_error_enter_thread(void) {
  194. wi_error_t *error;
  195. error = _wi_error_init(_wi_error_alloc());
  196. wi_dictionary_set_data_for_key(wi_thread_dictionary(), error, WI_STR(_WI_ERROR_THREAD_KEY));
  197. wi_release(error);
  198. wi_error_set_error(WI_ERROR_DOMAIN_NONE, WI_ERROR_NONE);
  199. #ifdef HAVE_LIBXML_PARSER_H
  200. xmlSetGenericErrorFunc(NULL, _wi_error_xml_error_handler);
  201. #endif
  202. }
  203. #pragma mark -
  204. void wi_error_set_error(wi_error_domain_t domain, int code) {
  205. wi_error_t *error;
  206. error = _wi_error_get_error();
  207. error->domain = domain;
  208. error->code = code;
  209. wi_release(error->string);
  210. error->string = NULL;
  211. }
  212. void wi_error_set_errno(int code) {
  213. wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, code);
  214. }
  215. #ifdef HAVE_OPENSSL_SHA_H
  216. void wi_error_set_openssl_error(void) {
  217. wi_error_t *error;
  218. const char *file;
  219. int line;
  220. if(ERR_peek_error() == 0) {
  221. wi_error_set_errno(errno);
  222. } else {
  223. error = _wi_error_get_error();
  224. error->domain = WI_ERROR_DOMAIN_OPENSSL;
  225. error->code = ERR_get_error_line(&file, &line);
  226. wi_release(error->string);
  227. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s:%d: %s: %s (%u)"),
  228. file,
  229. line,
  230. ERR_func_error_string(error->code),
  231. ERR_reason_error_string(error->code),
  232. ERR_GET_REASON(error->code));
  233. }
  234. ERR_clear_error();
  235. }
  236. #endif
  237. #ifdef HAVE_OPENSSL_SSL_H
  238. void wi_error_set_openssl_ssl_error_with_result(void *ssl, int result) {
  239. wi_error_t *error;
  240. int code;
  241. code = SSL_get_error(ssl, result);
  242. if(code == SSL_ERROR_SYSCALL) {
  243. if(ERR_peek_error() == 0) {
  244. if(result == 0)
  245. wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
  246. else
  247. wi_error_set_errno(errno);
  248. } else {
  249. wi_error_set_openssl_error();
  250. }
  251. }
  252. else if(code == SSL_ERROR_SSL) {
  253. wi_error_set_openssl_error();
  254. } else {
  255. error = _wi_error_get_error();
  256. error->domain = WI_ERROR_DOMAIN_OPENSSL_SSL;
  257. error->code = code;
  258. wi_release(error->string);
  259. switch(error->code) {
  260. case SSL_ERROR_NONE:
  261. error->string = wi_retain(WI_STR("SSL: No error"));
  262. break;
  263. case SSL_ERROR_ZERO_RETURN:
  264. error->string = wi_retain(WI_STR("SSL: Zero return"));
  265. break;
  266. case SSL_ERROR_WANT_READ:
  267. error->string = wi_retain(WI_STR("SSL: Want read"));
  268. break;
  269. case SSL_ERROR_WANT_WRITE:
  270. error->string = wi_retain(WI_STR("SSL: Want write"));
  271. break;
  272. case SSL_ERROR_WANT_CONNECT:
  273. error->string = wi_retain(WI_STR("SSL: Want connect"));
  274. break;
  275. case SSL_ERROR_WANT_ACCEPT:
  276. error->string = wi_retain(WI_STR("SSL: Want accept"));
  277. break;
  278. case SSL_ERROR_WANT_X509_LOOKUP:
  279. error->string = wi_retain(WI_STR("SSL: Want X509 lookup"));
  280. break;
  281. }
  282. }
  283. ERR_clear_error();
  284. }
  285. #endif
  286. #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
  287. void wi_error_set_commoncrypto_error(int code) {
  288. wi_error_t *error;
  289. error = _wi_error_get_error();
  290. error->domain = WI_ERROR_DOMAIN_COMMONCRYPTO;
  291. error->code = code;
  292. wi_release(error->string);
  293. switch(code) {
  294. case kCCParamError:
  295. error->string = wi_retain(WI_STR("Illegal parameter value"));
  296. break;
  297. case kCCBufferTooSmall:
  298. error->string = wi_retain(WI_STR("Insufficent buffer provided for specified operation"));
  299. break;
  300. case kCCMemoryFailure:
  301. error->string = wi_retain(WI_STR("Memory allocation failure"));
  302. break;
  303. case kCCAlignmentError:
  304. error->string = wi_retain(WI_STR("Input size was not aligned properly"));
  305. break;
  306. case kCCDecodeError:
  307. error->string = wi_retain(WI_STR("Input data did not decode or decrypt properly"));
  308. break;
  309. case kCCUnimplemented:
  310. error->string = wi_retain(WI_STR("Function not implemented for the current algorithm"));
  311. break;
  312. }
  313. }
  314. #endif
  315. #ifdef HAVE_LIBXML_PARSER_H
  316. void wi_error_set_libxml2_error(void) {
  317. wi_error_t *error;
  318. xmlErrorPtr xml_error;
  319. xml_error = xmlGetLastError();
  320. error = _wi_error_get_error();
  321. error->domain = WI_ERROR_DOMAIN_REGEX;
  322. error->code = xml_error->code;
  323. wi_release(error->string);
  324. error->string = wi_string_init_with_cstring(wi_string_alloc(), xml_error->message);
  325. wi_string_delete_surrounding_whitespace(error->string);
  326. }
  327. #endif
  328. void wi_error_set_regex_error(regex_t *regex, int code) {
  329. wi_error_t *error;
  330. char string[256];
  331. error = _wi_error_get_error();
  332. error->domain = WI_ERROR_DOMAIN_REGEX;
  333. error->code = code;
  334. wi_release(error->string);
  335. regerror(code, regex, string, sizeof(string));
  336. error->string = wi_string_init_with_cstring(wi_string_alloc(), string);
  337. }
  338. #ifdef HAVE_ZLIB_H
  339. void wi_error_set_zlib_error(int code) {
  340. if(code == Z_ERRNO)
  341. wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
  342. else
  343. wi_error_set_error(WI_ERROR_DOMAIN_ZLIB, code);
  344. }
  345. #endif
  346. void wi_error_set_carbon_error(int code) {
  347. wi_error_set_error(WI_ERROR_DOMAIN_CARBON, code);
  348. }
  349. void wi_error_set_libwired_error(int code) {
  350. wi_error_set_error(WI_ERROR_DOMAIN_LIBWIRED, code);
  351. }
  352. void wi_error_set_libwired_error_with_string(int code, wi_string_t *string) {
  353. wi_error_t *error;
  354. error = _wi_error_get_error();
  355. error->domain = WI_ERROR_DOMAIN_LIBWIRED;
  356. error->code = code;
  357. wi_release(error->string);
  358. error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
  359. if(wi_string_length(string) > 0) {
  360. if(wi_string_length(error->string) > 0)
  361. wi_string_append_string(error->string, WI_STR(": "));
  362. wi_string_append_string(error->string, string);
  363. }
  364. }
  365. void wi_error_set_libwired_error_with_format(int code, wi_string_t *fmt, ...) {
  366. wi_string_t *string;
  367. va_list ap;
  368. va_start(ap, fmt);
  369. string = wi_string_with_format_and_arguments(fmt, ap);
  370. va_end(ap);
  371. wi_error_set_libwired_error_with_string(code, string);
  372. }
  373. #pragma mark -
  374. wi_string_t * wi_error_string(void) {
  375. wi_error_t *error;
  376. error = _wi_error_get_error();
  377. if(!error->string) {
  378. switch(error->domain) {
  379. case WI_ERROR_DOMAIN_ERRNO:
  380. error->string = wi_string_init_with_cstring(wi_string_alloc(), strerror(error->code));
  381. break;
  382. case WI_ERROR_DOMAIN_GAI:
  383. error->string = wi_string_init_with_cstring(wi_string_alloc(), gai_strerror(error->code));
  384. break;
  385. case WI_ERROR_DOMAIN_REGEX:
  386. case WI_ERROR_DOMAIN_OPENSSL:
  387. case WI_ERROR_DOMAIN_OPENSSL_SSL:
  388. case WI_ERROR_DOMAIN_COMMONCRYPTO:
  389. case WI_ERROR_DOMAIN_LIBXML2:
  390. break;
  391. case WI_ERROR_DOMAIN_ZLIB:
  392. #ifdef HAVE_ZLIB_H
  393. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("zlib: %s"), zError(error->code));
  394. #endif
  395. break;
  396. case WI_ERROR_DOMAIN_CARBON:
  397. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Carbon: %d"), error->code);
  398. break;
  399. case WI_ERROR_DOMAIN_LIBWIRED:
  400. error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
  401. break;
  402. case WI_ERROR_DOMAIN_NONE:
  403. error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Unknown error domain: %d"), error->code);
  404. break;
  405. }
  406. }
  407. return error->string;
  408. }
  409. wi_error_domain_t wi_error_domain(void) {
  410. wi_error_t *error;
  411. error = _wi_error_get_error();
  412. return error->domain;
  413. }
  414. wi_integer_t wi_error_code(void) {
  415. wi_error_t *error;
  416. error = _wi_error_get_error();
  417. return error->code;
  418. }