PageRenderTime 31ms CodeModel.GetById 17ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/balrog/zanka-full
C | 410 lines | 231 code | 129 blank | 50 comment | 9 complexity | 9782f31d081c933819c577febebeaf8b MD5 | raw file
  1/* $Id$ */
  2
  3/*
  4 *  Copyright (c) 2003-2007 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 WI_CRYPTO
 39#include <openssl/err.h>
 40#endif
 41
 42#ifdef WI_SSL
 43#include <openssl/ssl.h>
 44#endif
 45
 46#ifdef WI_LIBXML2
 47#include <libxml/xmlerror.h>
 48#endif
 49
 50#ifdef WI_ZLIB
 51#include <zlib.h>
 52#endif
 53
 54#include <wired/wi-assert.h>
 55#include <wired/wi-error.h>
 56#include <wired/wi-hash.h>
 57#include <wired/wi-private.h>
 58#include <wired/wi-runtime.h>
 59#include <wired/wi-string.h>
 60#include <wired/wi-thread.h>
 61
 62#define _WI_ERROR_THREAD_KEY			"_wi_error_t"
 63
 64
 65struct _wi_error {
 66	wi_runtime_base_t					base;
 67	
 68	wi_string_t							*string;
 69	wi_error_domain_t					domain;
 70	wi_integer_t						code;
 71};
 72
 73
 74static wi_error_t *						_wi_error_alloc(void);
 75static wi_error_t *						_wi_error_init(wi_error_t *);
 76static void								_wi_error_dealloc(wi_runtime_instance_t *);
 77
 78static wi_error_t *						_wi_get_error(void);
 79
 80
 81static const char 						*_wi_error_strings[] = {
 82	/* WI_ERROR_NONE */
 83	"No error",
 84
 85	/* WI_ERROR_ADDRESS_NOAVAILABLEADDRESSES */
 86	"No available addresses",
 87	
 88	/* WI_ERROR_HOST_NOAVAILABLEADDRESSES */
 89	"No available addresses",
 90	
 91	/* WI_ERROR_LOG_NOSUCHFACILITY */
 92	"No such syslog facility",
 93	
 94	/* WI_ERROR_P7_INVALIDSPEC */
 95	"Invalid specification",
 96	/* WI_ERROR_P7_INVALIDMESSAGE */
 97	"Invalid message",
 98	/* WI_ERROR_P7_UNKNOWNMESSAGE */
 99	"Unknown message",
100	/* WI_ERROR_P7_UNKNOWNFIELD */
101	"Unknown field",
102	/* WI_ERROR_P7_HANDSHAKEFAILED */
103	"Handshake failed",
104	/* WI_ERROR_P7_CHECKSUMMISMATCH */
105	"Checksum mismatch",
106	
107	/* WI_ERROR_REGEXP_NOSLASH */
108	"Missing \"/\"",
109	/* WI_ERROR_REGEXP_INVALIDOPTION */
110	"Invalid option",
111	
112	/* WI_ERROR_SETTINGS_SYNTAXERROR */
113	"Syntax error",
114	/* WI_ERROR_SETTINGS_UNKNOWNSETTING */
115	"Unknown setting name",
116	/* WI_ERROR_SETTINGS_NOSUCHUSER */
117	"User not found",
118	/* WI_ERROR_SETTINGS_NOSUCHGROUP */
119	"Group not found",
120	/* WI_ERROR_SETTINGS_INVALIDPORT */
121	"Port is not in 1-65535 range",
122	/* WI_ERROR_SETTINGS_NOSUCHSERVICE */
123	"Service not found",
124
125	/* WI_ERROR_SOCKET_NOVALIDCIPHER */
126	"No valid cipher",
127	/* WI_ERROR_SOCKET_NOSSL */
128	"Socket has no SSL support",
129	/* WI_ERROR_SOCKET_EOF */
130	"End of file",
131	
132	/* WI_ERROR_TERMCAP_NOSUCHENTRY */
133	"No such entry in termcap database",
134	/* WI_ERROR_TERMCAP_TERMINFONOTFOUND */
135	"Termcap databse not found",
136
137	/* WI_ERROR_THREADS_NOTSUPP */
138	"Threads are not supported in this build",
139};
140
141static wi_runtime_id_t					_wi_error_runtime_id = WI_RUNTIME_ID_NULL;
142static wi_runtime_class_t				_wi_error_runtime_class = {
143	"wi_error_t",
144	_wi_error_dealloc,
145	NULL,
146	NULL,
147	NULL,
148	NULL
149};
150
151
152
153void wi_error_register(void) {
154	_wi_error_runtime_id = wi_runtime_register_class(&_wi_error_runtime_class);
155}
156
157
158
159void wi_error_initialize(void) {
160#ifdef WI_SSL
161	SSL_load_error_strings();
162#endif
163	
164#ifdef WI_CRYPTO
165	ERR_load_crypto_strings();
166#endif
167}
168
169
170
171#pragma mark -
172
173static wi_error_t * _wi_error_alloc(void) {
174	return wi_runtime_create_instance(_wi_error_runtime_id, sizeof(wi_error_t));
175}
176
177
178
179static wi_error_t * _wi_error_init(wi_error_t *error) {
180	return error;
181}
182
183
184
185static void _wi_error_dealloc(wi_runtime_instance_t *instance) {
186	wi_error_t		*error = instance;
187	
188	wi_release(error->string);
189}
190
191
192
193#pragma mark -
194
195static wi_error_t * _wi_get_error(void) {
196	wi_error_t		*error;
197	
198	error = wi_hash_data_for_key(wi_thread_hash(), WI_STR(_WI_ERROR_THREAD_KEY));
199
200	WI_ASSERT(error != NULL, "no wi_error_t created for thread", 0);
201	
202	return error;
203}
204
205
206
207#pragma mark -
208
209void wi_error_enter_thread(void) {
210	wi_error_t		*error;
211
212	error = _wi_error_init(_wi_error_alloc());
213	wi_hash_set_data_for_key(wi_thread_hash(), error, WI_STR(_WI_ERROR_THREAD_KEY));
214	wi_release(error);
215	
216	wi_error_set_error(WI_ERROR_DOMAIN_NONE, WI_ERROR_NONE);
217}
218
219
220
221void wi_error_set_error(wi_error_domain_t domain, int code) {
222	wi_error_t		*error;
223
224	error = _wi_get_error();
225	error->domain = domain;
226	error->code = code;
227
228	wi_release(error->string);
229	error->string = NULL;
230}
231
232
233
234void wi_error_set_errno(int code) {
235	wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, code);
236}
237
238
239
240#if defined(WI_CRYPTO) || defined(WI_SSL)
241
242void wi_error_set_openssl_error(void) {
243	wi_error_t		*error;
244	const char		*file;
245	int				line;
246
247	if(ERR_peek_error() == 0) {
248		wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
249	} else {
250		error = _wi_get_error();
251		error->domain = WI_ERROR_DOMAIN_OPENSSL;
252		error->code = ERR_get_error_line(&file, &line);
253		
254		wi_release(error->string);
255
256		error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("%s:%d: %s: %s (%u)"),
257			file,
258			line,
259			ERR_func_error_string(error->code),
260			ERR_reason_error_string(error->code),
261			ERR_GET_REASON(error->code));
262	}
263}
264
265#endif
266
267
268
269#ifdef WI_LIBXML2
270
271void wi_error_set_libxml2_error(void) {
272	wi_error_t		*error;
273	xmlErrorPtr		xml_error;
274
275	xml_error = xmlGetLastError();
276
277	error = _wi_get_error();
278	error->domain = WI_ERROR_DOMAIN_REGEX;
279	error->code = xml_error->code;
280	
281	wi_release(error->string);
282
283	error->string = wi_string_init_with_cstring(wi_string_alloc(), xml_error->message);
284	wi_string_delete_surrounding_whitespace(error->string);
285}
286
287#endif
288
289
290
291void wi_error_set_regex_error(regex_t *regex, int code) {
292	wi_error_t		*error;
293	char			string[256];
294
295	error = _wi_get_error();
296	error->domain = WI_ERROR_DOMAIN_REGEX;
297	error->code = code;
298	
299	wi_release(error->string);
300
301	regerror(code, regex, string, sizeof(string));
302
303	error->string = wi_string_init_with_cstring(wi_string_alloc(), string);
304}
305
306
307
308#ifdef WI_ZLIB
309
310void wi_error_set_zlib_error(int code) {
311	if(code == Z_ERRNO)
312		wi_error_set_error(WI_ERROR_DOMAIN_ERRNO, errno);
313	else
314		wi_error_set_error(WI_ERROR_DOMAIN_ZLIB, code);
315}
316
317#endif
318
319
320
321void wi_error_set_libwired_error(int code) {
322	wi_error_set_error(WI_ERROR_DOMAIN_LIBWIRED, code);
323}
324
325
326
327void wi_error_set_libwired_p7_error(int code, wi_string_t *fmt, ...) {
328	wi_error_t		*error;
329	va_list			ap;
330
331	error = _wi_get_error();
332	error->domain = WI_ERROR_DOMAIN_LIBWIRED;
333	error->code = code;
334	
335	wi_release(error->string);
336	
337	error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
338
339	if(wi_string_length(fmt) > 0) {
340		wi_string_append_string(error->string, WI_STR(": "));
341
342		va_start(ap, fmt);
343		wi_string_append_format_and_arguments(error->string, fmt, ap);
344		va_end(ap);
345	}
346}
347
348
349
350#pragma mark -
351
352wi_string_t * wi_error_string(void) {
353	wi_error_t		*error;
354
355	error = _wi_get_error();
356
357	if(!error->string) {
358		switch(error->domain) {
359			case WI_ERROR_DOMAIN_ERRNO:
360				error->string = wi_string_init_with_cstring(wi_string_alloc(), strerror(error->code));
361				break;
362
363			case WI_ERROR_DOMAIN_GAI:
364				error->string = wi_string_init_with_cstring(wi_string_alloc(), gai_strerror(error->code));
365				break;
366
367			case WI_ERROR_DOMAIN_REGEX:
368				break;
369
370			case WI_ERROR_DOMAIN_OPENSSL:
371				break;
372				
373			case WI_ERROR_DOMAIN_LIBXML2:
374				break;
375			
376			case WI_ERROR_DOMAIN_ZLIB:
377#ifdef WI_ZLIB
378				error->string = wi_string_init_with_format(wi_string_alloc(), WI_STR("zlib: %s"), zError(error->code));
379#endif
380				break;
381
382			case WI_ERROR_DOMAIN_NONE:
383			case WI_ERROR_DOMAIN_LIBWIRED:
384				error->string = wi_string_init_with_cstring(wi_string_alloc(), _wi_error_strings[error->code]);
385				break;
386		}
387	}
388
389	return error->string;
390}
391
392
393
394wi_error_domain_t wi_error_domain(void) {
395	wi_error_t		*error;
396
397	error = _wi_get_error();
398
399	return error->domain;
400}
401
402
403
404wi_integer_t wi_error_code(void) {
405	wi_error_t		*error;
406
407	error = _wi_get_error();
408
409	return error->code;
410}