PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

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

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