PageRenderTime 58ms CodeModel.GetById 36ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

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