PageRenderTime 70ms CodeModel.GetById 13ms app.highlight 51ms RepoModel.GetById 1ms 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/*
  4 *  Copyright (c) 2003-2009 Axel Andersson
  5 *  All rights reserved.
  6 *
  7 *  Redistribution and use in source and binary forms, with or without
  8 *  modification, are permitted provided that the following conditions
  9 *  are met:
 10 *  1. Redistributions of source code must retain the above copyright
 11 *     notice, this list of conditions and the following disclaimer.
 12 *  2. Redistributions in binary form must reproduce the above copyright
 13 *     notice, this list of conditions and the following disclaimer in the
 14 *     documentation and/or other materials provided with the distribution.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 19 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 26 * POSSIBILITY OF SUCH DAMAGE.
 27 */
 28
 29#include "config.h"
 30
 31#include <sys/types.h>
 32#include <sys/socket.h>
 33#include <netdb.h>
 34#include <string.h>
 35#include <errno.h>
 36#include <regex.h>
 37
 38#ifdef HAVE_OPENSSL_SHA_H
 39#include <openssl/err.h>
 40#endif
 41
 42#ifdef HAVE_OPENSSL_SSL_H
 43#include <openssl/ssl.h>
 44#endif
 45
 46#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
 47#include <CommonCrypto/CommonCryptor.h>
 48#endif
 49
 50#ifdef HAVE_LIBXML_PARSER_H
 51#include <libxml/xmlerror.h>
 52#endif
 53
 54#ifdef HAVE_ZLIB_H
 55#include <zlib.h>
 56#endif
 57
 58#include <wired/wi-assert.h>
 59#include <wired/wi-dictionary.h>
 60#include <wired/wi-error.h>
 61#include <wired/wi-private.h>
 62#include <wired/wi-runtime.h>
 63#include <wired/wi-string.h>
 64#include <wired/wi-thread.h>
 65
 66#define _WI_ERROR_THREAD_KEY			"_wi_error_t"
 67
 68
 69struct _wi_error {
 70	wi_runtime_base_t					base;
 71	
 72	wi_string_t							*string;
 73	wi_error_domain_t					domain;
 74	wi_integer_t						code;
 75};
 76
 77
 78static wi_error_t *						_wi_error_alloc(void);
 79static wi_error_t *						_wi_error_init(wi_error_t *);
 80static void								_wi_error_dealloc(wi_runtime_instance_t *);
 81
 82static wi_error_t *						_wi_error_get_error(void);
 83
 84#ifdef HAVE_LIBXML_PARSER_H
 85static void								_wi_error_xml_error_handler(void *, const char *, ...);
 86#endif
 87
 88
 89static const char 						*_wi_error_strings[] = {
 90	/* WI_ERROR_NONE */
 91	"No error",
 92
 93	/* WI_ERROR_ADDRESS_NOAVAILABLEADDRESSES */
 94	"No available addresses",
 95
 96	/* WI_ERROR_CIPHER_CIPHERNOTSUPP */
 97	"Cipher not supported",
 98	
 99	/* WI_ERROR_FILE_NOCARBON */
100	"Carbon not supported",
101
102	/* WI_ERROR_FSEVENTS_NOTSUPP */
103	"No compatible API available",
104	
105	/* WI_ERROR_HOST_NOAVAILABLEADDRESSES */
106	"No available addresses",
107	
108	/* WI_ERROR_LOG_NOSUCHFACILITY */
109	"No such syslog facility",
110	
111	/* WI_ERROR_P7_INVALIDSPEC */
112	"Invalid specification",
113	/* WI_ERROR_P7_INVALIDMESSAGE */
114	"Invalid message",
115	/* WI_ERROR_P7_UNKNOWNMESSAGE */
116	"Unknown message",
117	/* WI_ERROR_P7_UNKNOWNFIELD */
118	"Unknown field",
119	/* WI_ERROR_P7_HANDSHAKEFAILED */
120	"Handshake failed",
121	/* WI_ERROR_P7_INCOMPATIBLE_SPEC */
122	"",
123	/* WI_ERROR_P7_AUTHENTICATIONFAILED */
124	"Authentication failed",
125	/* WI_ERROR_P7_CHECKSUMMISMATCH */
126	"Checksum mismatch",
127	/* WI_ERROR_P7_NORSAKEY */
128	"No private RSA key set",
129	/* WI_ERROR_P7_MESSAGETOOLARGE */
130	"Message too large",
131	/* WI_ERROR_P7_RSANOTSUPP */
132	"RSA not supported",
133
134	/* WI_ERROR_PLIST_READFAILED */
135	"Property list read failed",
136	/* WI_ERROR_PLIST_WRITEFAILED */
137	"Property list write failed",
138	
139	/* WI_ERROR_REGEXP_NOSLASH */
140	"Missing \"/\"",
141	/* WI_ERROR_REGEXP_INVALIDOPTION */
142	"Invalid option",
143	
144	/* WI_ERROR_SETTINGS_SYNTAXERROR */
145	"Syntax error",
146	/* WI_ERROR_SETTINGS_UNKNOWNSETTING */
147	"Unknown setting name",
148	/* WI_ERROR_SETTINGS_NOSUCHUSER */
149	"User not found",
150	/* WI_ERROR_SETTINGS_NOSUCHGROUP */
151	"Group not found",
152	/* WI_ERROR_SETTINGS_INVALIDPORT */
153	"Port is not in 1-65535 range",
154	/* WI_ERROR_SETTINGS_NOSUCHSERVICE */
155	"Service not found",
156
157	/* WI_ERROR_SOCKET_NOVALIDCIPHER */
158	"No valid cipher",
159	/* WI_ERROR_SOCKET_EOF */
160	"End of file",
161	
162	/* WI_ERROR_SSL_ERROR_NONE */
163	"OpenSSL: No error",
164	/* WI_ERROR_SSL_ERROR_ZERO_RETURN */
165	"OpenSSL: Zero return",
166	/* WI_ERROR_SSL_ERROR_WANT_READ */
167	"OpenSSL: Want read",
168	/* WI_ERROR_SSL_ERROR_WANT_WRITE */
169	"OpenSSL: Want write",
170	/* WI_ERROR_SSL_ERROR_WANT_CONNECT */
171	"OpenSSL: Want connect",
172	/* WI_ERROR_SSL_ERROR_WANT_ACCEPT */
173	"OpenSSL: Want accept",
174	/* WI_ERROR_SSL_ERROR_WANT_X509_LOOKUP */
175	"OpenSSL: Want X509 lookup",
176
177	/* WI_ERROR_TERMCAP_NOSUCHENTRY */
178	"No such entry in termcap database",
179	/* WI_ERROR_TERMCAP_TERMINFONOTFOUND */
180	"Termcap databse not found",
181};
182
183static wi_runtime_id_t					_wi_error_runtime_id = WI_RUNTIME_ID_NULL;
184static wi_runtime_class_t				_wi_error_runtime_class = {
185	"wi_error_t",
186	_wi_error_dealloc,
187	NULL,
188	NULL,
189	NULL,
190	NULL
191};
192
193
194
195void wi_error_register(void) {
196	_wi_error_runtime_id = wi_runtime_register_class(&_wi_error_runtime_class);
197}
198
199
200
201void wi_error_initialize(void) {
202#ifdef HAVE_OPENSSL_SSL_H
203	SSL_load_error_strings();
204#endif
205	
206#ifdef HAVE_OPENSSL_SHA_H
207	ERR_load_crypto_strings();
208#endif
209}
210
211
212
213#pragma mark -
214
215static wi_error_t * _wi_error_alloc(void) {
216	return wi_runtime_create_instance(_wi_error_runtime_id, sizeof(wi_error_t));
217}
218
219
220
221static wi_error_t * _wi_error_init(wi_error_t *error) {
222	return error;
223}
224
225
226
227static void _wi_error_dealloc(wi_runtime_instance_t *instance) {
228	wi_error_t		*error = instance;
229	
230	wi_release(error->string);
231}
232
233
234
235#pragma mark -
236
237static wi_error_t * _wi_error_get_error(void) {
238	wi_error_t		*error;
239	
240	error = wi_dictionary_data_for_key(wi_thread_dictionary(), WI_STR(_WI_ERROR_THREAD_KEY));
241
242	WI_ASSERT(error != NULL, "no wi_error_t created for thread", 0);
243	
244	return error;
245}
246
247
248
249#ifdef HAVE_LIBXML_PARSER_H
250
251static void _wi_error_xml_error_handler(void *context, const char *message, ...) {
252}
253
254#endif
255
256
257
258#pragma mark -
259
260void wi_error_enter_thread(void) {
261	wi_error_t		*error;
262
263	error = _wi_error_init(_wi_error_alloc());
264	wi_dictionary_set_data_for_key(wi_thread_dictionary(), error, WI_STR(_WI_ERROR_THREAD_KEY));
265	wi_release(error);
266	
267	wi_error_set_error(WI_ERROR_DOMAIN_NONE, WI_ERROR_NONE);
268	
269#ifdef HAVE_LIBXML_PARSER_H
270	xmlSetGenericErrorFunc(NULL, _wi_error_xml_error_handler);
271#endif
272}
273
274
275
276#pragma mark -
277
278void wi_error_set_error(wi_error_domain_t domain, int code) {
279	wi_error_t		*error;
280
281	error = _wi_error_get_error();
282	error->domain = domain;
283	error->code = code;
284
285	wi_release(error->string);
286	error->string = NULL;
287}
288
289
290
291void wi_error_set_errno(int code) {
292	wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, code);
293}
294
295
296
297#ifdef HAVE_OPENSSL_SHA_H
298
299void wi_error_set_openssl_error(void) {
300	wi_error_t		*error;
301	const char		*file;
302	int				line;
303
304	if(ERR_peek_error() == 0) {
305		wi_error_set_errno(errno);
306	} else {
307		error = _wi_error_get_error();
308		error->domain = WI_ERROR_DOMAIN_OPENSSL;
309		error->code = ERR_get_error_line(&file, &line);
310		
311		wi_release(error->string);
312
313		error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s:%d: %s: %s (%u)"),
314			file,
315			line,
316			ERR_func_error_string(error->code),
317			ERR_reason_error_string(error->code),
318			ERR_GET_REASON(error->code));
319	}
320	
321	ERR_clear_error();
322}
323
324#endif
325
326
327
328#ifdef HAVE_OPENSSL_SSL_H
329
330void wi_error_set_openssl_ssl_error_with_result(void *ssl, int result) {
331	wi_error_t		*error;
332	int				code;
333	
334	code = SSL_get_error(ssl, result);
335	
336	if(code == SSL_ERROR_SYSCALL) {
337		if(ERR_peek_error() == 0) {
338			if(result == 0)
339				wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
340			else
341				wi_error_set_errno(errno);
342		} else {
343			wi_error_set_openssl_error();
344		}
345	}
346	else if(code == SSL_ERROR_SSL) {
347		wi_error_set_openssl_error();
348	} else {
349		error = _wi_error_get_error();
350		error->domain = WI_ERROR_DOMAIN_OPENSSL_SSL;
351		error->code = code;
352
353		wi_release(error->string);
354
355		switch(error->code) {
356			case SSL_ERROR_NONE:
357				error->string = wi_retain(WI_STR("SSL: No error"));
358				break;
359
360			case SSL_ERROR_ZERO_RETURN:
361				error->string = wi_retain(WI_STR("SSL: Zero return"));
362				break;
363				
364			case SSL_ERROR_WANT_READ:
365				error->string = wi_retain(WI_STR("SSL: Want read"));
366				break;
367				
368			case SSL_ERROR_WANT_WRITE:
369				error->string = wi_retain(WI_STR("SSL: Want write"));
370				break;
371				
372			case SSL_ERROR_WANT_CONNECT:
373				error->string = wi_retain(WI_STR("SSL: Want connect"));
374				break;
375				
376			case SSL_ERROR_WANT_ACCEPT:
377				error->string = wi_retain(WI_STR("SSL: Want accept"));
378				break;
379				
380			case SSL_ERROR_WANT_X509_LOOKUP:
381				error->string = wi_retain(WI_STR("SSL: Want X509 lookup"));
382				break;
383		}
384	}
385	
386	ERR_clear_error();
387}
388
389#endif
390
391
392
393#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
394
395void wi_error_set_commoncrypto_error(int code) {
396	wi_error_t		*error;
397	
398	error = _wi_error_get_error();
399	error->domain = WI_ERROR_DOMAIN_COMMONCRYPTO;
400	error->code = code;
401	
402	wi_release(error->string);
403
404	switch(code) {
405		case kCCParamError:
406			error->string = wi_retain(WI_STR("Illegal parameter value"));
407			break;
408
409		case kCCBufferTooSmall:
410			error->string = wi_retain(WI_STR("Insufficent buffer provided for specified operation"));
411			break;
412
413		case kCCMemoryFailure:
414			error->string = wi_retain(WI_STR("Memory allocation failure"));
415			break;
416
417		case kCCAlignmentError:
418			error->string = wi_retain(WI_STR("Input size was not aligned properly"));
419			break;
420
421		case kCCDecodeError:
422			error->string = wi_retain(WI_STR("Input data did not decode or decrypt properly"));
423			break;
424
425		case kCCUnimplemented:
426			error->string = wi_retain(WI_STR("Function not implemented for the current algorithm"));
427			break;
428	}
429}
430
431#endif
432
433
434
435#ifdef HAVE_LIBXML_PARSER_H
436
437void wi_error_set_libxml2_error(void) {
438	wi_error_t		*error;
439	xmlErrorPtr		xml_error;
440
441	xml_error = xmlGetLastError();
442
443	error = _wi_error_get_error();
444	error->domain = WI_ERROR_DOMAIN_REGEX;
445	error->code = xml_error->code;
446	
447	wi_release(error->string);
448
449	error->string = wi_string_init_with_cstring(wi_string_alloc(), xml_error->message);
450	wi_string_delete_surrounding_whitespace(error->string);
451}
452
453#endif
454
455
456
457void wi_error_set_regex_error(regex_t *regex, int code) {
458	wi_error_t		*error;
459	char			string[256];
460
461	error = _wi_error_get_error();
462	error->domain = WI_ERROR_DOMAIN_REGEX;
463	error->code = code;
464	
465	wi_release(error->string);
466
467	regerror(code, regex, string, sizeof(string));
468
469	error->string = wi_string_init_with_cstring(wi_string_alloc(), string);
470}
471
472
473
474#ifdef HAVE_ZLIB_H
475
476void wi_error_set_zlib_error(int code) {
477	if(code == Z_ERRNO)
478		wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
479	else
480		wi_error_set_error(WI_ERROR_DOMAIN_ZLIB, code);
481}
482
483#endif
484
485
486
487void wi_error_set_carbon_error(int code) {
488	wi_error_set_error(WI_ERROR_DOMAIN_CARBON, code);
489}
490
491
492
493void wi_error_set_libwired_error(int code) {
494	wi_error_set_error(WI_ERROR_DOMAIN_LIBWIRED, code);
495}
496
497
498
499void wi_error_set_libwired_error_with_string(int code, wi_string_t *string) {
500	wi_error_t		*error;
501
502	error = _wi_error_get_error();
503	error->domain = WI_ERROR_DOMAIN_LIBWIRED;
504	error->code = code;
505	
506	wi_release(error->string);
507	
508	error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
509
510	if(wi_string_length(string) > 0) {
511		if(wi_string_length(error->string) > 0)
512			wi_string_append_string(error->string, WI_STR(": "));
513		
514		wi_string_append_string(error->string, string);
515	}
516}
517
518
519
520void wi_error_set_libwired_error_with_format(int code, wi_string_t *fmt, ...) {
521	wi_string_t		*string;
522	va_list			ap;
523
524	va_start(ap, fmt);
525	string = wi_string_with_format_and_arguments(fmt, ap);
526	va_end(ap);
527	
528	wi_error_set_libwired_error_with_string(code, string);
529}
530
531
532
533#pragma mark -
534
535wi_string_t * wi_error_string(void) {
536	wi_error_t		*error;
537
538	error = _wi_error_get_error();
539
540	if(!error->string) {
541		switch(error->domain) {
542			case WI_ERROR_DOMAIN_ERRNO:
543				error->string = wi_string_init_with_cstring(wi_string_alloc(), strerror(error->code));
544				break;
545
546			case WI_ERROR_DOMAIN_GAI:
547				error->string = wi_string_init_with_cstring(wi_string_alloc(), gai_strerror(error->code));
548				break;
549
550			case WI_ERROR_DOMAIN_REGEX:
551			case WI_ERROR_DOMAIN_OPENSSL:
552			case WI_ERROR_DOMAIN_OPENSSL_SSL:
553			case WI_ERROR_DOMAIN_COMMONCRYPTO:
554			case WI_ERROR_DOMAIN_LIBXML2:
555				break;
556			
557			case WI_ERROR_DOMAIN_ZLIB:
558#ifdef HAVE_ZLIB_H
559				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("zlib: %s"), zError(error->code));
560#endif
561				break;
562			
563			case WI_ERROR_DOMAIN_CARBON:
564				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Carbon: %d"), error->code);
565				break;
566
567			case WI_ERROR_DOMAIN_LIBWIRED:
568				error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
569				break;
570
571			case WI_ERROR_DOMAIN_NONE:
572				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Unknown error domain: %d"), error->code);
573				break;
574		}
575	}
576
577	return error->string;
578}
579
580
581
582wi_error_domain_t wi_error_domain(void) {
583	wi_error_t		*error;
584
585	error = _wi_error_get_error();
586
587	return error->domain;
588}
589
590
591
592wi_integer_t wi_error_code(void) {
593	wi_error_t		*error;
594
595	error = _wi_error_get_error();
596
597	return error->code;
598}