PageRenderTime 41ms CodeModel.GetById 16ms app.highlight 20ms RepoModel.GetById 1ms 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/*
  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_INVALIDARGUMENT */
116	"Invalid argument",
117	/* WI_ERROR_P7_UNKNOWNMESSAGE */
118	"Unknown message",
119	/* WI_ERROR_P7_UNKNOWNFIELD */
120	"Unknown field",
121	/* WI_ERROR_P7_HANDSHAKEFAILED */
122	"Handshake failed",
123	/* WI_ERROR_P7_INCOMPATIBLESPEC */
124	"",
125	/* WI_ERROR_P7_AUTHENTICATIONFAILED */
126	"Authentication failed",
127	/* WI_ERROR_P7_CHECKSUMMISMATCH */
128	"Checksum mismatch",
129	/* WI_ERROR_P7_NORSAKEY */
130	"No private RSA key set",
131	/* WI_ERROR_P7_MESSAGETOOLARGE */
132	"Message too large",
133	/* WI_ERROR_P7_RSANOTSUPP */
134	"RSA not supported",
135
136	/* WI_ERROR_PLIST_READFAILED */
137	"Property list read failed",
138	/* WI_ERROR_PLIST_WRITEFAILED */
139	"Property list write failed",
140	
141	/* WI_ERROR_REGEXP_NOSLASH */
142	"Missing \"/\"",
143	/* WI_ERROR_REGEXP_INVALIDOPTION */
144	"Invalid option",
145	
146	/* WI_ERROR_SETTINGS_SYNTAXERROR */
147	"Syntax error",
148	/* WI_ERROR_SETTINGS_UNKNOWNSETTING */
149	"Unknown setting name",
150	/* WI_ERROR_SETTINGS_NOSUCHUSER */
151	"User not found",
152	/* WI_ERROR_SETTINGS_NOSUCHGROUP */
153	"Group not found",
154	/* WI_ERROR_SETTINGS_INVALIDPORT */
155	"Port is not in 1-65535 range",
156	/* WI_ERROR_SETTINGS_NOSUCHSERVICE */
157	"Service not found",
158
159	/* WI_ERROR_SOCKET_NOVALIDCIPHER */
160	"No valid cipher",
161	/* WI_ERROR_SOCKET_EOF */
162	"End of file",
163	/* WI_ERROR_SOCKET_OVERFLOW */
164	"Buffer overflow",
165	
166	/* WI_ERROR_SSL_ERROR_NONE */
167	"OpenSSL: No error",
168	/* WI_ERROR_SSL_ERROR_ZERO_RETURN */
169	"OpenSSL: Zero return",
170	/* WI_ERROR_SSL_ERROR_WANT_READ */
171	"OpenSSL: Want read",
172	/* WI_ERROR_SSL_ERROR_WANT_WRITE */
173	"OpenSSL: Want write",
174	/* WI_ERROR_SSL_ERROR_WANT_CONNECT */
175	"OpenSSL: Want connect",
176	/* WI_ERROR_SSL_ERROR_WANT_ACCEPT */
177	"OpenSSL: Want accept",
178	/* WI_ERROR_SSL_ERROR_WANT_X509_LOOKUP */
179	"OpenSSL: Want X509 lookup",
180
181	/* WI_ERROR_TERMCAP_NOSUCHENTRY */
182	"No such entry in termcap database",
183	/* WI_ERROR_TERMCAP_TERMINFONOTFOUND */
184	"Termcap databse not found",
185};
186
187static wi_runtime_id_t					_wi_error_runtime_id = WI_RUNTIME_ID_NULL;
188static wi_runtime_class_t				_wi_error_runtime_class = {
189	"wi_error_t",
190	_wi_error_dealloc,
191	NULL,
192	NULL,
193	NULL,
194	NULL
195};
196
197
198
199void wi_error_register(void) {
200	_wi_error_runtime_id = wi_runtime_register_class(&_wi_error_runtime_class);
201}
202
203
204
205void wi_error_initialize(void) {
206#ifdef HAVE_OPENSSL_SSL_H
207	SSL_load_error_strings();
208#endif
209	
210#ifdef HAVE_OPENSSL_SHA_H
211	ERR_load_crypto_strings();
212#endif
213}
214
215
216
217#pragma mark -
218
219static wi_error_t * _wi_error_alloc(void) {
220	return wi_runtime_create_instance(_wi_error_runtime_id, sizeof(wi_error_t));
221}
222
223
224
225static wi_error_t * _wi_error_init(wi_error_t *error) {
226	return error;
227}
228
229
230
231static void _wi_error_dealloc(wi_runtime_instance_t *instance) {
232	wi_error_t		*error = instance;
233	
234	wi_release(error->string);
235}
236
237
238
239#pragma mark -
240
241static wi_error_t * _wi_error_get_error(void) {
242	wi_error_t		*error;
243	
244	error = wi_dictionary_data_for_key(wi_thread_dictionary(), WI_STR(_WI_ERROR_THREAD_KEY));
245
246	WI_ASSERT(error != NULL, "no wi_error_t created for thread", 0);
247	
248	return error;
249}
250
251
252
253#ifdef HAVE_LIBXML_PARSER_H
254
255static void _wi_error_xml_error_handler(void *context, const char *message, ...) {
256}
257
258#endif
259
260
261
262#pragma mark -
263
264void wi_error_enter_thread(void) {
265	wi_error_t		*error;
266
267	error = _wi_error_init(_wi_error_alloc());
268	wi_mutable_dictionary_set_data_for_key(wi_thread_dictionary(), error, WI_STR(_WI_ERROR_THREAD_KEY));
269	wi_release(error);
270	
271	wi_error_set_error(WI_ERROR_DOMAIN_NONE, WI_ERROR_NONE);
272	
273#ifdef HAVE_LIBXML_PARSER_H
274	xmlSetGenericErrorFunc(NULL, _wi_error_xml_error_handler);
275#endif
276}
277
278
279
280#pragma mark -
281
282void wi_error_set_error(wi_error_domain_t domain, int code) {
283	wi_error_t		*error;
284
285	error = _wi_error_get_error();
286	error->domain = domain;
287	error->code = code;
288
289	wi_release(error->string);
290	error->string = NULL;
291}
292
293
294
295void wi_error_set_errno(int code) {
296	wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, code);
297}
298
299
300
301#ifdef HAVE_OPENSSL_SHA_H
302
303void wi_error_set_openssl_error(void) {
304	wi_error_t		*error;
305	const char		*file;
306	int				line;
307
308	if(ERR_peek_error() == 0) {
309		wi_error_set_errno(errno);
310	} else {
311		error = _wi_error_get_error();
312		error->domain = WI_ERROR_DOMAIN_OPENSSL;
313		error->code = ERR_get_error_line(&file, &line);
314		
315		wi_release(error->string);
316
317		error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s:%d: %s: %s (%u)"),
318			file,
319			line,
320			ERR_func_error_string(error->code),
321			ERR_reason_error_string(error->code),
322			ERR_GET_REASON(error->code));
323	}
324	
325	ERR_clear_error();
326}
327
328#endif
329
330
331
332#ifdef HAVE_OPENSSL_SSL_H
333
334void wi_error_set_openssl_ssl_error_with_result(void *ssl, int result) {
335	wi_error_t		*error;
336	int				code;
337	
338	code = SSL_get_error(ssl, result);
339	
340	if(code == SSL_ERROR_SYSCALL) {
341		if(ERR_peek_error() == 0) {
342			if(result == 0)
343				wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
344			else
345				wi_error_set_errno(errno);
346		} else {
347			wi_error_set_openssl_error();
348		}
349	}
350	else if(code == SSL_ERROR_SSL) {
351		wi_error_set_openssl_error();
352	} else {
353		error = _wi_error_get_error();
354		error->domain = WI_ERROR_DOMAIN_OPENSSL_SSL;
355		error->code = code;
356
357		wi_release(error->string);
358
359		switch(error->code) {
360			case SSL_ERROR_NONE:
361				error->string = wi_retain(WI_STR("SSL: No error"));
362				break;
363
364			case SSL_ERROR_ZERO_RETURN:
365				error->string = wi_retain(WI_STR("SSL: Zero return"));
366				break;
367				
368			case SSL_ERROR_WANT_READ:
369				error->string = wi_retain(WI_STR("SSL: Want read"));
370				break;
371				
372			case SSL_ERROR_WANT_WRITE:
373				error->string = wi_retain(WI_STR("SSL: Want write"));
374				break;
375				
376			case SSL_ERROR_WANT_CONNECT:
377				error->string = wi_retain(WI_STR("SSL: Want connect"));
378				break;
379				
380			case SSL_ERROR_WANT_ACCEPT:
381				error->string = wi_retain(WI_STR("SSL: Want accept"));
382				break;
383				
384			case SSL_ERROR_WANT_X509_LOOKUP:
385				error->string = wi_retain(WI_STR("SSL: Want X509 lookup"));
386				break;
387		}
388	}
389	
390	ERR_clear_error();
391}
392
393#endif
394
395
396
397#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
398
399void wi_error_set_commoncrypto_error(int code) {
400	wi_error_t		*error;
401	
402	error = _wi_error_get_error();
403	error->domain = WI_ERROR_DOMAIN_COMMONCRYPTO;
404	error->code = code;
405	
406	wi_release(error->string);
407
408	switch(code) {
409		case kCCParamError:
410			error->string = wi_retain(WI_STR("Illegal parameter value"));
411			break;
412
413		case kCCBufferTooSmall:
414			error->string = wi_retain(WI_STR("Insufficent buffer provided for specified operation"));
415			break;
416
417		case kCCMemoryFailure:
418			error->string = wi_retain(WI_STR("Memory allocation failure"));
419			break;
420
421		case kCCAlignmentError:
422			error->string = wi_retain(WI_STR("Input size was not aligned properly"));
423			break;
424
425		case kCCDecodeError:
426			error->string = wi_retain(WI_STR("Input data did not decode or decrypt properly"));
427			break;
428
429		case kCCUnimplemented:
430			error->string = wi_retain(WI_STR("Function not implemented for the current algorithm"));
431			break;
432	}
433}
434
435#endif
436
437
438
439#ifdef HAVE_LIBXML_PARSER_H
440
441void wi_error_set_libxml2_error(void) {
442	wi_error_t		*error;
443	wi_string_t		*string;
444	xmlErrorPtr		xml_error;
445
446	xml_error = xmlGetLastError();
447
448	error = _wi_error_get_error();
449	error->domain = WI_ERROR_DOMAIN_REGEX;
450	error->code = xml_error->code;
451	
452	string = wi_string_by_deleting_surrounding_whitespace(wi_string_with_cstring(xml_error->message));
453	
454	wi_release(error->string);
455	error->string = wi_retain(string);
456}
457
458#endif
459
460
461
462void wi_error_set_regex_error(regex_t *regex, int code) {
463	wi_error_t		*error;
464	char			string[256];
465
466	error = _wi_error_get_error();
467	error->domain = WI_ERROR_DOMAIN_REGEX;
468	error->code = code;
469	
470	regerror(code, regex, string, sizeof(string));
471
472	wi_release(error->string);
473	error->string = wi_string_init_with_cstring(wi_string_alloc(), string);
474}
475
476
477
478#ifdef HAVE_ZLIB_H
479
480void wi_error_set_zlib_error(int code) {
481	if(code == Z_ERRNO)
482		wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
483	else
484		wi_error_set_error(WI_ERROR_DOMAIN_ZLIB, code);
485}
486
487#endif
488
489
490
491void wi_error_set_carbon_error(int code) {
492	wi_error_set_error(WI_ERROR_DOMAIN_CARBON, code);
493}
494
495
496
497void wi_error_set_libwired_error(int code) {
498	wi_error_set_error(WI_ERROR_DOMAIN_LIBWIRED, code);
499}
500
501
502
503void wi_error_set_libwired_error_with_string(int code, wi_string_t *string) {
504	wi_error_t		*error;
505
506	error = _wi_error_get_error();
507	error->domain = WI_ERROR_DOMAIN_LIBWIRED;
508	error->code = code;
509	
510	wi_release(error->string);
511	
512	error->string = wi_string_init_with_cstring(wi_mutable_string_alloc(), _wi_error_strings[error->code]);
513
514	if(wi_string_length(string) > 0) {
515		if(wi_string_length(error->string) > 0)
516			wi_mutable_string_append_string(error->string, WI_STR(": "));
517		
518		wi_mutable_string_append_string(error->string, string);
519	}
520}
521
522
523
524void wi_error_set_libwired_error_with_format(int code, wi_string_t *fmt, ...) {
525	wi_string_t		*string;
526	va_list			ap;
527
528	va_start(ap, fmt);
529	string = wi_string_with_format_and_arguments(fmt, ap);
530	va_end(ap);
531	
532	wi_error_set_libwired_error_with_string(code, string);
533}
534
535
536
537#pragma mark -
538
539wi_string_t * wi_error_string(void) {
540	wi_error_t		*error;
541
542	error = _wi_error_get_error();
543
544	if(!error->string) {
545		switch(error->domain) {
546			case WI_ERROR_DOMAIN_ERRNO:
547				error->string = wi_string_init_with_cstring(wi_string_alloc(), strerror(error->code));
548				break;
549
550			case WI_ERROR_DOMAIN_GAI:
551				error->string = wi_string_init_with_cstring(wi_string_alloc(), gai_strerror(error->code));
552				break;
553
554			case WI_ERROR_DOMAIN_REGEX:
555			case WI_ERROR_DOMAIN_OPENSSL:
556			case WI_ERROR_DOMAIN_OPENSSL_SSL:
557			case WI_ERROR_DOMAIN_COMMONCRYPTO:
558			case WI_ERROR_DOMAIN_LIBXML2:
559				break;
560			
561			case WI_ERROR_DOMAIN_ZLIB:
562#ifdef HAVE_ZLIB_H
563				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("zlib: %s"), zError(error->code));
564#endif
565				break;
566			
567			case WI_ERROR_DOMAIN_CARBON:
568				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Carbon: %d"), error->code);
569				break;
570
571			case WI_ERROR_DOMAIN_LIBWIRED:
572				error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
573				break;
574
575			case WI_ERROR_DOMAIN_NONE:
576				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("Unknown error domain: %d"), error->code);
577				break;
578		}
579	}
580
581	return error->string;
582}
583
584
585
586wi_error_domain_t wi_error_domain(void) {
587	wi_error_t		*error;
588
589	error = _wi_error_get_error();
590
591	return error->domain;
592}
593
594
595
596wi_integer_t wi_error_code(void) {
597	wi_error_t		*error;
598
599	error = _wi_error_get_error();
600
601	return error->code;
602}