PageRenderTime 53ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

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

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