+Sat Dec 22 19:55:28 EET 2007 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added SILC errno API to lib/silcutil/silcerrno.[ch]. Added
+ SilcResult, generic error code and return value type. Added
+ global silc_errno that returns last error in that thread.
+
+ * Deprecated SilcSocketStreamStatus, SilcResult replaces it.
+ Backwards support remains. Affected files are
+ lib/silcutil/silcsocketstream.[ch].
+
+ * Deprecated SilcNetStatus, SilcResult replaces it. Backwards
+ support remains. Affected files are lib/silcutil/silcnet.[ch].
+
+ * Added errno setting to almost all Runtime Tooolkit routines
+ in error conditions.
+
Sun Dec 16 16:18:04 EET 2007 Pekka Riikonen <priikone@silcnet.org>
* Added SILC Bit Operations API to lib/silcutil/silcbitops.[ch].
o Change silc_gettimeofday on Unix to use clock_gettime with REALTIME
clock if it is available, otherwise use gettimeofday(). (***DONE)
+ o Generic SilcResult that includes all possible status and
+ error conditions and generic errno API. (***DONE)
+
(o SilcIpAddr abstraction. Ipv4 and Ipv6 support to the abstaction.)
maybe
- (o Generic SilcStatus or SilcResult that includes all possible status and
- error conditions, including those of SILC protocol. Though, the SILC
- protocol related status (currently in silcstatus.h) cannot be in
- runtime library) maybe
-
(o SILC specific socket creation/closing routines to silcnet.h, wrappers
to all send(), recv(), sendto() etc. Bad thing is that we'd have to
define all socket options, sockaddrs, etc.) maybe
#endif /* !SILC_WIN32 */
/* Include generic SILC type definitions */
+#include "silcerrno.h"
#include "silctypes.h"
+#include "silcbitops.h"
#include "silcmutex.h"
#include "silcatomic.h"
#include "silcversion.h"
/* Callback called after connected to remote host */
-static void silc_client_connect_callback(SilcNetStatus status,
+static void silc_client_connect_callback(SilcResult status,
SilcStream stream, void *context)
{
SilcFSMThread fsm = context;
conn->internal->op = NULL;
if (conn->internal->verbose) {
switch (status) {
- case SILC_NET_OK:
+ case SILC_OK:
break;
- case SILC_NET_UNKNOWN_IP:
+ case SILC_ERR_UNKNOWN_IP:
client->internal->ops->say(
client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Could not connect to host %s: unknown IP address",
conn->remote_host);
break;
- case SILC_NET_UNKNOWN_HOST:
+ case SILC_ERR_UNKNOWN_HOST:
client->internal->ops->say(
client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Could not connect to host %s: unknown host name",
conn->remote_host);
break;
- case SILC_NET_HOST_UNREACHABLE:
+ case SILC_ERR_UNREACHABLE:
client->internal->ops->say(
client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Could not connect to host %s: network unreachable",
conn->remote_host);
break;
- case SILC_NET_CONNECTION_REFUSED:
+ case SILC_ERR_REFUSED:
client->internal->ops->say(
client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Could not connect to host %s: connection refused",
conn->remote_host);
break;
- case SILC_NET_CONNECTION_TIMEOUT:
+ case SILC_ERR_TIMEOUT:
client->internal->ops->say(
client, conn, SILC_CLIENT_MESSAGE_ERROR,
"Could not connect to host %s: connection timeout",
}
}
- if (status != SILC_NET_OK) {
+ if (status != SILC_OK) {
/* Notify application of failure */
SILC_LOG_DEBUG(("Connecting failed"));
conn->internal->status = SILC_CLIENT_CONN_ERROR;
conn->remote_host, conn->remote_port,
conn->internal->schedule);
- SILC_FSM_CALL(silc_client_connect_callback(stream ? SILC_NET_OK :
- SILC_NET_HOST_UNREACHABLE,
+ SILC_FSM_CALL(silc_client_connect_callback(stream ? SILC_OK :
+ SILC_ERR_UNREACHABLE,
stream, fsm));
} else {
/* Connect (TCP) */
/* TCP network listener callback. Accepts new key agreement connection.
Responder function. */
-static void silc_client_listener_tcp_accept(SilcNetStatus status,
+static void silc_client_listener_tcp_accept(SilcResult status,
SilcStream stream,
void *context)
{
* stream_create_cb, app);
*
* // Stream callback delivers our new SilcStream context
- * void stream_create_cb(SilcSocketStreamStatus status, SilcStream stream,
+ * void stream_create_cb(SilcResult status, SilcStream stream,
* void *context)
* {
* ...
- * if (status != SILC_SOCKET_OK)
+ * if (status != SILC_OK)
* error(status);
*
* // Start key exchange
/* Accepts new connection */
-static void silc_http_server_new_connection(SilcNetStatus status,
+static void silc_http_server_new_connection(SilcResult status,
SilcStream stream,
void *context)
{
silcdll.c \
silcenv.c \
silcbase64.c \
- silcbitops.c
+ silcbitops.c \
+ silcerrno.c
#ifdef SILC_DIST_TOOLKIT
include_HEADERS = \
silcdll.h \
silcenv.h \
silcbase64.h \
- silcbitops.h
+ silcbitops.h \
+ silcerrno.h
SILC_EXTRA_DIST = tests
#endif SILC_DIST_TOOLKIT
}
}
- switch(char_count) {
+ switch (char_count) {
case 1:
silc_sfree(stack, data);
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
return NULL;
break;
case 2:
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit);
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return FALSE;
+ }
bitmap[pos] |= mask;
return TRUE;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit);
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
bitmap[pos] &= ~mask;
return TRUE;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit);
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
bitmap[pos] ^= mask;
return TRUE;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit), ret;
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return -1;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return -1;
+ }
ret = bitmap[pos];
bitmap[pos] ^= mask;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit), ret;
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return -1;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return -1;
+ }
ret = bitmap[pos];
bitmap[pos] &= ~mask;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit), ret;
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return -1;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return -1;
+ }
ret = bitmap[pos];
bitmap[pos] ^= mask;
SilcUInt32 pos = SILC_BIT_POS(bit);
unsigned long mask = SILC_BIT_MASK(bit);
- if (!bitmap || pos >= bitmap_size)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return -1;
+ }
+ if (pos >= bitmap_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return -1;
+ }
return (bitmap[pos] & mask) != 0;
}
{
register SilcUInt32 i;
- if (!bitmap || offset >= bitmap_size * SILC_BIT_SIZE)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return -1;
+ }
+ if (offset >= bitmap_size * SILC_BIT_SIZE) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return -1;
+ }
for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
if (bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i))
return i;
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return -1;
}
{
register SilcUInt32 i;
- if (!bitmap || offset >= bitmap_size * SILC_BIT_SIZE)
+ if (!bitmap) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return -1;
+ }
+ if (offset >= bitmap_size * SILC_BIT_SIZE) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return -1;
+ }
for (i = offset; i < bitmap_size * SILC_BIT_SIZE; i++)
if ((bitmap[SILC_BIT_POS(i)] & SILC_BIT_MASK(i)) == 0)
return i;
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return -1;
}
* find bits in an arbitrarily large bitmap. The interface does not support
* setting the bits atomically.
*
- * Example with a pre-allocate bitmap:
+ * Example with a pre-allocated bitmap:
*
* // Declare bitmap of size of 500 bits
* SILC_BITMAP_DECLARE(bitmap, 500);
* bit = silc_bit_ffs(bitmap, bitmap_size);
*
* // Find next set bit from the bitmap
- * bit = silc_bit_fns(bitmap, bitmap_size, bit);
+ * bit = silc_bit_fns(bitmap, bitmap_size, bit + 1);
*
* // Clear bit number 100
* silc_bit_set(bitmap, bitmap_size, 100);
* SYNOPSIS
*
* int silc_bit_get(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
- * ,SilcUInt32 bit);
+ * SilcUInt32 bit);
*
* DESCRIPTION
*
* DESCRIPTION
*
* Returns the bit number of the first set bit in the `bitmap' of size
- * of `bitmap_size'. Returns -1 on error or there were no set bits.
+ * of `bitmap_size'. Returns -1 on error or when there were no set bits.
*
***/
int silc_bit_ffs(volatile unsigned long *bitmap, SilcUInt32 bitmap_size);
* DESCRIPTION
*
* Returns the bit number of the first zero bit in the `bitmap' of size
- * of `bitmap_size'. Returns -1 on error or there were no zero bits.
+ * of `bitmap_size'. Returns -1 on error or when there were no zero bits.
*
***/
int silc_bit_ffz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size);
*
* Returns the bit number of the next set bit in the `bitmap' of size
* of `bitmap_size' starting at bit `offset'. Returns -1 on error or
- * there were no more set bits.
+ * when there were no more set bits.
*
***/
int silc_bit_fns(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
*
* Returns the bit number of the next zero bit in the `bitmap' of size
* of `bitmap_size' starting at bit `offset'. Returns -1 on error or
- * there were no more zero bits.
+ * when there were no more zero bits.
*
***/
int silc_bit_fnz(volatile unsigned long *bitmap, SilcUInt32 bitmap_size,
#ifdef SILC_DIST_INPLACE
SILC_ASSERT(len <= silc_buffer_len(sb));
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely(len > silc_buffer_len(sb)))
+ if (silc_unlikely(len > silc_buffer_len(sb))) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return NULL;
+ }
sb->data += len;
return old_data;
#ifdef SILC_DIST_INPLACE
SILC_ASSERT((sb->data - len) >= sb->head);
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely((sb->data - len) < sb->head))
+ if (silc_unlikely((sb->data - len) < sb->head)) {
+ silc_set_errno(SILC_ERR_UNDERFLOW);
return NULL;
+ }
sb->data -= len;
return old_data;
#ifdef SILC_DIST_INPLACE
SILC_ASSERT(len <= silc_buffer_taillen(sb));
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely(len > silc_buffer_taillen(sb)))
+ if (silc_unlikely(len > silc_buffer_taillen(sb))) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return NULL;
+ }
sb->tail += len;
return old_tail;
#ifdef SILC_DIST_INPLACE
SILC_ASSERT((sb->tail - len) >= sb->data);
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely((sb->tail - len) < sb->data))
+ if (silc_unlikely((sb->tail - len) < sb->data)) {
+ silc_set_errno(SILC_ERR_UNDERFLOW);
return NULL;
+ }
sb->tail -= len;
return old_tail;
#ifdef SILC_DIST_INPLACE
SILC_ASSERT(len <= silc_buffer_headlen(sb));
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely(len > silc_buffer_headlen(sb)))
+ if (silc_unlikely(len > silc_buffer_headlen(sb))) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return NULL;
+ }
return (unsigned char *)memcpy(sb->head, data, len);
}
#ifdef SILC_DIST_INPLACE
SILC_ASSERT(len <= silc_buffer_len(sb));
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely(len > silc_buffer_len(sb)))
+ if (silc_unlikely(len > silc_buffer_len(sb))) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return NULL;
+ }
return (unsigned char *)memcpy(sb->data, data, len);
}
#ifdef SILC_DIST_INPLACE
SILC_ASSERT(len <= silc_buffer_taillen(sb));
#endif /* SILC_DIST_INPLACE */
- if (silc_unlikely(len > silc_buffer_taillen(sb)))
+ if (silc_unlikely(len > silc_buffer_taillen(sb))) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return NULL;
+ }
return (unsigned char *)memcpy(sb->tail, data, len);
}
} while(0)
/* Check that there is data to be unformatted */
-#define UNFORMAT_HAS_SPACE(b, req) \
-do { \
- if (silc_unlikely(req > silc_buffer_len(b))) \
- goto fail; \
- if (silc_unlikely((req + 1) <= 0)) \
- goto fail; \
+#define UNFORMAT_HAS_SPACE(b, req) \
+do { \
+ if (silc_unlikely(req > silc_buffer_len(b))) { \
+ silc_set_errno(SILC_ERR_OVERFLOW); \
+ goto fail; \
+ } \
+ if (silc_unlikely((req + 1) <= 0)) { \
+ silc_set_errno(SILC_ERR_UNDERFLOW); \
+ goto fail; \
+ } \
} while(0)
if (!offst)
break;
if (offst > 1) {
- if (offst > silc_buffer_len(dst))
+ if (offst > silc_buffer_len(dst)) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto fail;
+ }
silc_buffer_pull(dst, offst);
flen += offst;
} else {
default:
SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
"format the data.", fmt));
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
+ "Bad buffer formatting type %d", fmt);
goto fail;
break;
}
default:
SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
"format the data.", fmt));
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
+ "Bad buffer formatting type %d", fmt);
goto fail;
break;
}
Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- Copyright (C) 2002 - 2006 Giovanni Giacobbi
+ Copyright (C) 2002 - 2007 Giovanni Giacobbi
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#else
/* XXX Symbian */
#endif /* SILC_UNIX */
- SILC_LOG_ERROR(("Shared objects are not supported on this platform"));
+ silc_set_errno_reason(SILC_ERR_NOT_SUPPORTED,
+ "Shared objects are not supported on this platform");
return NULL;
}
#else
/* XXX Symbian */
#endif /* SILC_UNIX */
- SILC_LOG_ERROR(("Shared objects are not supported on this platform"));
+ silc_set_errno_reason(SILC_ERR_NOT_SUPPORTED,
+ "Shared objects are not supported on this platform");
return NULL;
}
--- /dev/null
+/*
+
+ silcerrno.c
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2007 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+#include "silc.h"
+
+/* Get last error */
+
+SilcResult silc_get_errno(void)
+{
+ SilcTls tls = silc_thread_get_tls();
+
+ if (!tls)
+ return SILC_OK;
+
+ return tls->error;
+}
+
+/* Set error */
+
+void silc_set_errno(SilcResult error)
+{
+ SilcTls tls = silc_thread_get_tls();
+
+ if (!tls) {
+ /* Try to create Tls */
+ tls = silc_thread_tls_init();
+ if (!tls)
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Error: %s (%d)", silc_errno_string(error), error));
+
+ tls->error_reason[0] = '\0';
+ tls->error = error;
+}
+
+/* Set error, cannot fail. */
+
+void silc_set_errno_nofail(SilcResult error)
+{
+ SilcTls tls = silc_thread_get_tls();
+
+ if (!tls)
+ return;
+
+ SILC_LOG_DEBUG(("Error: %s (%d)", silc_errno_string(error), error));
+
+ tls->error_reason[0] = '\0';
+ tls->error = error;
+}
+
+/* Set errno and reason for error. */
+
+void silc_set_errno_reason(SilcResult error, const char *format, ...)
+{
+ SilcTls tls = silc_thread_get_tls();
+ va_list va;
+
+ if (!tls) {
+ /* Try to create Tls */
+ tls = silc_thread_tls_init();
+ if (!tls)
+ return;
+ }
+
+ va_start(va, format);
+ silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
+ va_end(va);
+
+ SILC_LOG_DEBUG(("Error: %s (%d): %s", silc_errno_string(error), error,
+ tls->error_reason));
+
+ tls->error = error;
+}
+
+/* Set errno and reason for error, cannot fail. */
+
+void silc_set_errno_reason_nofail(SilcResult error, const char *format, ...)
+{
+ SilcTls tls = silc_thread_get_tls();
+ va_list va;
+
+ if (!tls)
+ return;
+
+ va_start(va, format);
+ silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
+ va_end(va);
+
+ SILC_LOG_DEBUG(("Error: %s (%d): %s", silc_errno_string(error), error,
+ tls->error_reason));
+
+ tls->error = error;
+}
+
+/* Set error from POSIX errno. */
+
+void silc_set_errno_posix(int error)
+{
+ if (!error)
+ return;
+
+#ifdef SILC_WIN32
+ /* WSA errors */
+ switch (error) {
+ case WSAEINTR:
+ silc_set_errno(SILC_ERR_INTERRUPTED);
+ break;
+ case WSAEBADF:
+ silc_set_errno(SILC_ERR_BAD_FD);
+ break;
+ case WSAEACCESS:
+ silc_set_errno(SILC_ERR_PERMISSION_DENIED);
+ break;
+ case WSAEFAULT:
+ silc_set_errno(SILC_ERR_BAD_ADDRESS);
+ break;
+ case WSA_INVALID_HANDLE:
+ case WSAENOTSOCK:
+ silc_set_errno(SILC_ERR_BAD_SOCKET);
+ break;
+ case WSA_INVALID_PARAMETER:
+ case WSAEINVAL:
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ break;
+ case WSA_NOT_ENOUGH_MEMORY:
+ silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
+ break;
+ case WSAEWOULDBLOCK:
+ silc_set_errno(SILC_ERR_WOULD_BLOCK);
+ break;
+ case WSAEOPNOTSUPPORT:
+ silc_set_errno(SILC_ERR_NOT_SUPPORTED);
+ break;
+ case WSAEADDRINUSE:
+ silc_set_errno(SILC_ERR_ADDR_IN_USE);
+ break;
+ case WSAEANETDOWN:
+ silc_set_errno(SILC_ERR_NET_DOWN);
+ break;
+ case WSAENETUNREACH:
+ case WSAEHOSTUNREACH:
+ silc_set_errno(SILC_ERR_UNREACHABLE);
+ break;
+ case WSAENETRESET:
+ silc_set_errno(SILC_ERR_RESET);
+ break;
+ case WSAECONNABORTED:
+ silc_set_errno(SILC_ERR_ABORTED);
+ break;
+ case WSAETIMEDOUT:
+ silc_set_errno(SILC_ERR_TIMEOUT);
+ break;
+ case WSAECONNREFUSED:
+ silc_set_errno(SILC_ERR_REFUSED);
+ break;
+ case WSAEHOSTDOWN:
+ silc_set_errno(SILC_ERR_HOST_DOWN);
+ break;
+ default:
+ silc_set_errno(SILC_ERR);
+ break;
+ }
+
+ return;
+#endif /* SILC_WIN32 */
+
+ /* POSIX, etc. errors */
+ switch (error) {
+#if defined(ENOMEM)
+ case ENOMEM:
+ silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
+ break;
+#endif
+#if defined(EAGAIN)
+ case EAGAIN:
+ silc_set_errno(SILC_ERR_WOULD_BLOCK);
+ break;
+#endif
+#if defined(EINVAL)
+ case EINVAL:
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ break;
+#endif
+#if defined(EINTR)
+ case EINTR:
+ silc_set_errno(SILC_ERR_INTERRUPTED);
+ break;
+#endif
+#if defined(EIO)
+ case EIO:
+ silc_set_errno(SILC_ERR_IO);
+ break;
+#endif
+#if defined(EPIPE)
+ case EPIPE:
+ silc_set_errno(SILC_ERR_BROKEN_PIPE);
+ break;
+#endif
+#if defined(ENOENT)
+ case ENOENT:
+ silc_set_errno(SILC_ERR_NO_SUCH_FILE);
+ break;
+#endif
+#if defined(EEXIST)
+ case EEXIST:
+ silc_set_errno(SILC_ERR_ALREADY_EXISTS);
+ break;
+#endif
+#if defined(ENOTDIR)
+ case ENOTDIR:
+ silc_set_errno(SILC_ERR_NOT_DIRECTORY);
+ break;
+#endif
+#if defined(EISDIR)
+ case EISDIR:
+ silc_set_errno(SILC_ERR_IS_DIRECTORY);
+ break;
+#endif
+#if defined(EBUSY)
+ case EBUSY:
+ silc_set_errno(SILC_ERR_BUSY);
+ break;
+#endif
+#if defined(ENODEV)
+ case ENODEV:
+ silc_set_errno(SILC_ERR_NO_SUCH_DEVICE);
+ break;
+#endif
+#if defined(ENOSPC)
+ case ENOSPC:
+ silc_set_errno(SILC_ERR_NO_SPACE_LEFT);
+ break;
+#endif
+#if defined(EROFS)
+ case EROFS:
+ silc_set_errno(SILC_ERR_READ_ONLY);
+ break;
+#endif
+#if defined(EBADFS)
+ case EBADFS:
+ silc_set_errno(SILC_ERR_BAD_FD);
+ break;
+#endif
+#if defined(EADDRINUSE)
+ case EADDRINUSE:
+ silc_set_errno(SILC_ERR_ADDR_IN_USE);
+ break;
+#endif
+#if defined(ECONNREFUSED)
+ case ECONNREFUSED:
+ silc_set_errno(SILC_ERR_REFUSED);
+ break;
+#endif
+#if defined(ECONNABORTED)
+ case ECONNABORTED:
+ silc_set_errno(SILC_ERR_ABORTED);
+ break;
+#endif
+#if defined(ECONNRESET)
+ case ECONNRESET:
+ silc_set_errno(SILC_ERR_RESET);
+ break;
+#endif
+#if defined(ENETUNREACH)
+ case ENETUNREACH:
+ silc_set_errno(SILC_ERR_UNREACHABLE);
+ break;
+#endif
+#if defined(EHOSTUNREACH)
+ case EHOSTUNREACH:
+ silc_set_errno(SILC_ERR_UNREACHABLE);
+ break;
+#endif
+#if defined(ENETDOWN)
+ case ENETDOWN:
+ silc_set_errno(SILC_ERR_NET_DOWN);
+ break;
+#endif
+#if defined(ETIMEDOUT)
+ case ETIMEDOUT:
+ silc_set_errno(SILC_ERR_TIMEOUT);
+ break;
+#endif
+#if defined(EHOSTDOWN)
+ case EHOSTDOWN:
+ silc_set_errno(SILC_ERR_HOST_DOWN);
+ break;
+#endif
+ default:
+ silc_set_errno(SILC_ERR);
+ break;
+ }
+}
+
+/* Get last reason for error */
+
+const char *silc_errno_reason(void)
+{
+ SilcTls tls = silc_thread_get_tls();
+
+ if (!tls || tls->error_reason[0] == '\0')
+ return (const char *)"";
+
+ return tls->error_reason;
+}
+
+const char *silc_errno_strings[] =
+{
+ "Ok",
+
+ "Error",
+ "Out of memory",
+ "Allocation by zero",
+ "Too large allocation",
+ "Overflow",
+ "Underflow",
+ "Feature not supported",
+ "Operation not permitted",
+ "Try again",
+ "Permission denied",
+ "Invalid argument",
+ "Bad time",
+ "Timeout",
+ "Assert",
+ "Not found",
+ "Unknown character",
+ "Prohibited character",
+ "Bad character encoding",
+ "Unsupported character encoding",
+ "Bad version",
+ "Bad memory address",
+ "Bad buffer encoding",
+ "Interrupted",
+ "Not valid",
+ "Limit reached",
+
+ "No such file or directory",
+ "Already exists",
+ "Not a directory",
+ "Is a directory",
+ "Directory not empty",
+ "Device or resource busy",
+ "No such device",
+ "No space left on device",
+ "Broken pipe",
+ "Read only",
+ "I/O error",
+ "Bad file descriptor",
+ "End of file",
+
+ "Bad IP address",
+ "Unknown IP address",
+ "Unknown host",
+ "Destination unreachable",
+ "Connection refused",
+ "Connection aborted",
+ "Connection reset by peer",
+ "Would block",
+ "Host is down",
+ "Bad socket",
+ "Bad stream",
+ "Address already in use",
+ "Network is down",
+ "End of stream",
+
+ NULL
+};
+
+/* Map error to string */
+
+const char *silc_errno_string(SilcResult error)
+{
+ if (error < 0 || error >= SILC_ERR_MAX)
+ return (const char *)"";
+
+ return silc_errno_strings[error];
+}
--- /dev/null
+/*
+
+ silcerrno.h
+
+ Author: Pekka Riikonen <priikone@silcnet.org>
+
+ Copyright (C) 2007 Pekka Riikonen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+*/
+
+/****h* silcutil/SILC Errno
+ *
+ * DESCRIPTION
+ *
+ * Error codes and routines for accessing the error codes in case of
+ * error condition. SILC Runtime toolkit contains a global silc_errno
+ * that contains the error code that occurred. Each thread has their own
+ * silc_errno.
+ *
+ * Each silc_errno error code can be mapped to a string that can be used
+ * to display the error for user. Some routines may also provide detailed
+ * reason why the error occurred. The reason string can be retrieved for
+ * the last error by using silc_errno_reason.
+ *
+ * EXAMPLE
+ *
+ * // Use silc_errno
+ * buf = silc_file_readfile(filename, &buf_len, NULL);
+ * if (buf == NULL) {
+ * fprintf(stderr, "Error reading file %s: %s (%d)", filename,
+ * silc_errno_string(silc_errno), silc_errno);
+ * exit(1);
+ * }
+ *
+ * // Get the detailed reason for the error too
+ * if (silc_some_routine() == FALSE) {
+ * fprintf(stderr, "%s (%d) (%s)", silc_errno_string(silc_errno),
+ * silc_errno, silc_errno_reason);
+ * exit(1);
+ * }
+ *
+ ***/
+
+#ifndef SILCERRNO_H
+#define SILCERRNO_H
+
+/****d* silcutil/SilcErrnoAPI/SilcResult
+ *
+ * NAME
+ *
+ * typedef enum { ... } SilcResult;
+ *
+ * DESCRIPTION
+ *
+ * Error codes.
+ *
+ * SOURCE
+ */
+typedef enum {
+ SILC_OK = 0, /* Ok, no error */
+
+ /* General errors */
+ SILC_ERR = 1, /* General error */
+ SILC_ERR_OUT_OF_MEMORY = 2, /* Out of memory */
+ SILC_ERR_ZERO_ALLOCATION = 3, /* Allocation by zero */
+ SILC_ERR_TOO_LARGE_ALLOCATION = 4, /* Too large allocation */
+ SILC_ERR_OVERFLOW = 5, /* Would overflow */
+ SILC_ERR_UNDERFLOW = 6, /* Would underflow */
+ SILC_ERR_NOT_SUPPORTED = 7, /* Feature not supported */
+ SILC_ERR_NOT_PERMITTED = 8, /* Operation not permitted */
+ SILC_ERR_TRY_AGAIN = 9, /* Try again */
+ SILC_ERR_PERMISSION_DENIED = 10, /* Permission denied */
+ SILC_ERR_INVALID_ARGUMENT = 11, /* Invalid argument */
+ SILC_ERR_BAD_TIME = 13, /* Bad time value */
+ SILC_ERR_TIMEOUT = 14, /* Timeout occurred */
+ SILC_ERR_ASSERT = 15, /* Assertion failed */
+ SILC_ERR_NOT_FOUND = 16, /* Item/entry not found */
+ SILC_ERR_UNKNOWN_CHAR = 17, /* Unknown character */
+ SILC_ERR_PROHIBITED_CHAR = 18, /* Prohibited character */
+ SILC_ERR_BAD_CHAR_ENCODING = 19, /* Bad character encoding */
+ SILC_ERR_UNSUPPORTED_CHAR_ENCODING = 20, /* Unsupported char encoding */
+ SILC_ERR_BAD_VERSION = 21, /* Bad/unsupported version */
+ SILC_ERR_BAD_ADDRESS = 22, /* Bad memory address */
+ SILC_ERR_BAD_ENCODING = 23, /* Bad data encoding */
+ SILC_ERR_INTERRUPTED = 24, /* Interrupted */
+ SILC_ERR_NOT_VALID = 25, /* Not valid */
+ SILC_ERR_LIMIT = 26, /* Limit reached */
+
+ /* File, directory and device errors */
+ SILC_ERR_NO_SUCH_FILE = 40, /* No such file */
+ SILC_ERR_ALREADY_EXISTS = 41, /* File already exists */
+ SILC_ERR_NOT_DIRECTORY = 42, /* Not a directory */
+ SILC_ERR_IS_DIRECTORY = 43, /* Is a directory */
+ SILC_ERR_NOT_EMPTY = 44, /* Directory not empty */
+ SILC_ERR_BUSY = 45, /* Device or resource busy */
+ SILC_ERR_NO_SUCH_DEVICE = 46, /* No such device */
+ SILC_ERR_NO_SPACE_LEFT = 47, /* No space left on device */
+ SILC_ERR_BROKEN_PIPE = 48, /* Broken pipe */
+ SILC_ERR_READ_ONLY = 49, /* Read only */
+ SILC_ERR_IO = 50, /* I/O error */
+ SILC_ERR_BAD_FD = 51, /* Bad file descriptor */
+ SILC_ERR_EOF = 52, /* End of file */
+
+ /* Network errors */
+ SILC_ERR_BAD_IP = 70, /* Bad IP address */
+ SILC_ERR_UNKNOWN_IP = 71, /* Unknown IP address */
+ SILC_ERR_UNKNOWN_HOST = 72, /* Unknown host name */
+ SILC_ERR_UNREACHABLE = 73, /* Destination unreachable */
+ SILC_ERR_REFUSED = 74, /* Connection refused */
+ SILC_ERR_ABORTED = 75, /* Connection aborted */
+ SILC_ERR_RESET = 76, /* Connection reset by peer */
+ SILC_ERR_WOULD_BLOCK = 77, /* Would block */
+ SILC_ERR_HOST_DOWN = 78, /* Host is down */
+ SILC_ERR_BAD_SOCKET = 79, /* Bad socket */
+ SILC_ERR_BAD_STREAM = 80, /* Bad stream */
+ SILC_ERR_ADDR_IN_USE = 81, /* Address already in use */
+ SILC_ERR_NET_DOWN = 82, /* Network is down */
+ SILC_ERR_EOS = 83, /* End of stream */
+
+ SILC_ERR_MAX,
+} SilcResult;
+/***/
+
+/****d* silcutil/SilcErrnoAPI/silc_errno
+ *
+ * NAME
+ *
+ * SilcResult silc_errno;
+ *
+ * DESCRIPTION
+ *
+ * Returns the error code of the last error. To map the error code to a
+ * string call silc_errno_string.
+ *
+ ***/
+#define silc_errno silc_get_errno()
+
+/****f* silcutil/SilcErrnoAPI/silc_errno_string
+ *
+ * NAME
+ *
+ * const char *silc_errno_string(SilcResult error);
+ *
+ * DESCRIPTION
+ *
+ * Returns the string of the error `errno'. This routine never returns
+ * NULL.
+ *
+ ***/
+const char *silc_errno_string(SilcResult error);
+
+/****d* silcutil/SilcErrnoAPI/silc_errno_string
+ *
+ * NAME
+ *
+ * const char *silc_errno_reason(void);
+ *
+ * DESCRIPTION
+ *
+ * Returns additional reason string for the last occurred error or ""
+ * if the additional information is not available. This routine never
+ * returns NULL.
+ *
+ ***/
+const char *silc_errno_reason(void);
+
+/* Low-level routines for the error handling. */
+
+/* Return last error */
+SilcResult silc_get_errno(void);
+
+/* Set error */
+void silc_set_errno(SilcResult error);
+
+/* Set error, cannot fail. */
+void silc_set_errno_nofail(SilcResult error);
+
+/* Set error and reason string. */
+void silc_set_errno_reason(SilcResult error, const char *format, ...);
+
+/* Set error and reason string, cannot fail. */
+void silc_set_errno_reason_nofail(SilcResult error, const char *format, ...);
+
+/* Set error from POSIX errno */
+void silc_set_errno_posix(int error);
+
+#endif /* SILCERRNO_H */
void *notifier_context;
int fd1;
int fd2;
- int error;
} *SilcFDStream;
SilcStream silc_fd_stream_create(int fd, SilcStack stack)
{
- if (fd < 1)
+ if (fd < 1) {
+ silc_set_errno_reason(SILC_ERR_BAD_FD, "Bad file descriptor %d", fd);
return NULL;
+ }
return silc_fd_stream_create2(fd, 0, stack);
}
{
const char *read_file = NULL, *write_file = NULL;
- if (!filename)
+ if (!filename) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
if (writing)
write_file = filename;
return TRUE;
}
-/* Return errno */
-
-int silc_fd_stream_get_error(SilcStream stream)
-{
- SilcFDStream fd_stream = stream;
-
- if (!SILC_IS_FD_STREAM(fd_stream))
- return 0;
-
- return fd_stream->error;
-}
-
/* Read */
int silc_fd_stream_read(SilcStream stream, unsigned char *buf,
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd1,
SILC_TASK_READ, FALSE);
+ silc_set_errno_posix(errno);
return -1;
}
SILC_LOG_DEBUG(("Cannot read from fd: %d:%s",
fd_stream->fd1, strerror(errno)));
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
- fd_stream->error = errno;
+ silc_set_errno_posix(errno);
return -2;
}
SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd2,
SILC_TASK_READ | SILC_TASK_WRITE, FALSE);
+ silc_set_errno_posix(errno);
return -1;
}
SILC_LOG_DEBUG(("Cannot write to fd: %s", strerror(errno)));
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
- fd_stream->error = errno;
+ silc_set_errno_posix(errno);
return -2;
}
SilcBool silc_fd_stream_get_info(SilcStream stream,
int *read_fd, int *write_fd);
-/****f* silcutil/SilcFDStreamAPI/silc_fd_stream_get_error
- *
- * SYNOPSIS
- *
- * int silc_fd_stream_get_error(SilcStream stream);
- *
- * DESCRIPTION
- *
- * If error occurred during file descriptor stream operations, this
- * function can be used to retrieve the error number that occurred.
- *
- ***/
-int silc_fd_stream_get_error(SilcStream stream);
+/* Backwards support */
+#define silc_fd_stream_get_error(stream) silc_errno
#endif /* SILCFDSTREAM_H */
int silc_file_open_mode(const char *filename, int flags, int mode)
{
int fd = open(filename, flags, mode);
+ if (fd < 0)
+ silc_set_errno_posix(errno);
return fd;
}
int silc_file_read(int fd, unsigned char *buf, SilcUInt32 buf_len)
{
- return read(fd, (void *)buf, buf_len);
+ int ret = read(fd, (void *)buf, buf_len);
+ if (ret < 0)
+ silc_set_errno_posix(errno);
+ return ret;
}
/* Writes `buffer' of length of `len' to file descriptor `fd'. */
int silc_file_write(int fd, const char *buffer, SilcUInt32 len)
{
- return write(fd, (const void *)buffer, len);
+ int ret = write(fd, (const void *)buffer, len);
+ if (ret < 0)
+ silc_set_errno_posix(errno);
+ return ret;
}
/* Closes file descriptor */
int silc_file_close(int fd)
{
- return close(fd);
+ int ret = close(fd);
+ if (ret < 0)
+ silc_set_errno_posix(errno);
+ return ret;
}
/* Writes a buffer to the file. */
if ((fd = open(filename, flags, 0644)) == -1) {
SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
- strerror(errno)));
+ silc_errno_string(silc_errno)));
return -1;
}
if (silc_file_write(fd, buffer, len) == -1) {
- SILC_LOG_ERROR(("Cannot write to file %s: %s", filename, strerror(errno)));
+ SILC_LOG_ERROR(("Cannot write to file %s: %s", filename,
+ silc_errno_string(silc_errno)));
silc_file_close(fd);
return -1;
}
if ((fd = open(filename, flags, mode)) == -1) {
SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
- strerror(errno)));
+ silc_errno_string(silc_errno)));
return -1;
}
if ((silc_file_write(fd, buffer, len)) == -1) {
- SILC_LOG_ERROR(("Cannot write to file %s: %s", filename, strerror(errno)));
+ SILC_LOG_ERROR(("Cannot write to file %s: %s", filename,
+ silc_errno_string(silc_errno)));
silc_file_close(fd);
return -1;
}
fd = silc_file_open(filename, O_RDONLY);
if (fd < 0) {
- if (errno == ENOENT)
+ if (silc_errno == SILC_ERR_NO_SUCH_FILE)
return NULL;
- SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
+ SILC_LOG_ERROR(("Cannot open file %s: %s", filename,
+ silc_errno_string(silc_errno)));
return NULL;
}
filelen = lseek(fd, (off_t)0L, SEEK_END);
if (filelen < 0) {
+ silc_set_errno_posix(errno);
silc_file_close(fd);
return NULL;
}
if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
- silc_file_close(fd);
- return NULL;
- }
-
- if (filelen < 0) {
- SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
+ silc_set_errno_posix(errno);
silc_file_close(fd);
return NULL;
}
memset(buffer, 0, sizeof(buffer));
silc_file_close(fd);
SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
- strerror(errno)));
+ silc_errno_string(silc_errno)));
return NULL;
}
#ifdef SILC_SYMBIAN
ret = stat(filename, &stats);
#endif /* SILC_SYMBIAN */
- if (ret < 0)
+ if (ret < 0) {
+ silc_set_errno_posix(errno);
return 0;
+ }
return (SilcUInt64)stats.st_size;
}
*
* Opens a file indicated by the filename `filename' with flags indicated
* by `flags'. The opening permission defaults to 0600. The `flags'
- * are defined in open(2).
+ * are defined in open(2). Returns the opened file descriptor or -1 on
+ * error.
*
***/
int silc_file_open(const char *filename, int flags);
* Opens a file indicated by the filename `filename' with flags indicated
* by `flags'. The argument `mode' specifies the permissions to use in
* case a new file is created. The `flags' are defined in open(2).
+ * Returns the opened file descriptor or -1 on error.
*
***/
int silc_file_open_mode(const char *filename, int flags, int mode);
*
* DESCRIPTION
*
- * Reads data from file descriptor `fd' to `buf'.
+ * Reads data from file descriptor `fd' to `buf'. Returns the amount of
+ * bytes read, 0 on EOF or -1 on error.
*
***/
int silc_file_read(int fd, unsigned char *buf, SilcUInt32 buf_len);
*
* DESCRIPTION
*
- * Writes `buffer' of length of `len' to file descriptor `fd'.
+ * Writes `buffer' of length of `len' to file descriptor `fd'. Returns
+ * the amount of bytes written, 0 on EOF or -1 on error.
*
***/
int silc_file_write(int fd, const char *buffer, SilcUInt32 len);
* DESCRIPTION
*
* Closes file descriptor previously opened with silc_file_open().
+ * Returns 0 on success or -1 on error.
*
***/
int silc_file_close(int fd);
void *destructor_context,
SilcSchedule schedule)
{
- if (!schedule)
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
fsm->fsm_context = fsm_context;
fsm->state_context = NULL;
} else {
/* Machine must not have active threads */
- assert(silc_atomic_get_int32(&fsm->u.m.threads) == 0);
+ SILC_VERIFY(silc_atomic_get_int32(&fsm->u.m.threads) == 0);
if (fsm->u.m.lock) {
silc_mutex_free(fsm->u.m.lock);
*
* DESCRIPTION
*
- * Moves to next state synchronously. This type is used is returned
- * from state functions to immediately move to next state.
+ * Moves to next state synchronously. This type is returned from state
+ * functions to immediately move to next state.
*
* EXAMPLE
*
SilcHashTable ht;
SilcUInt32 size_index = SILC_HASH_TABLE_SIZE;
- if (!hash)
+ if (!hash) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
if (stack)
stack = silc_stack_alloc(0, stack);
entry = silc_hash_table_find_internal(ht, key, &prev,
ht->hash, ht->hash_user_context,
ht->compare, ht->compare_user_context);
- if (*entry == NULL)
+ if (*entry == NULL) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
e = *entry;
compare_user_context ?
compare_user_context :
ht->compare_user_context);
- if (*entry == NULL)
+ if (*entry == NULL) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
e = *entry;
ht->hash_user_context,
ht->compare,
ht->compare_user_context);
- if (*entry == NULL)
+ if (*entry == NULL) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
e = *entry;
compare_user_context ?
compare_user_context :
ht->compare_user_context);
- if (*entry == NULL)
+ if (*entry == NULL) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
e = *entry;
compare_user_context ?
compare_user_context :
ht->compare_user_context);
- if (*entry == NULL)
+ if (*entry == NULL) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
if (ret_key)
*ret_key = (*entry)->key;
compare_user_context ?
compare_user_context :
ht->compare_user_context);
- if (!entry || !(*entry))
+ if (!entry || !(*entry)) {
+ silc_set_errno(SILC_ERR_NOT_FOUND);
return FALSE;
+ }
if (ret_key)
*ret_key = (*entry)->key;
int i;
SilcBool auto_rehash;
- if (!foreach)
- return;
+ if (!foreach) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
auto_rehash = ht->auto_rehash;
ht->auto_rehash = FALSE;
int len;
if ((strchr(debug_string, '(') && strchr(debug_string, ')')) ||
strchr(debug_string, '$'))
- string = strdup(debug_string);
+ string = silc_strdup(debug_string);
else
string = silc_string_regexify(debug_string);
len = strlen(string);
*
* DESCRIPTION
*
- * Verification macro that prints error message to stderr and calls
+ * Verification macro that prints error message to stderr and calls
* abort() if the `expression' is false (ie. compares equal to zero)
* on debug builds (SILC_DEBUG defined), and prints error message to
* stderr on release builds (SILC_DEBUG undefined) but does not abort().
#define SILC_VERIFY(expr) assert((expr));
#else
#define SILC_VERIFY(expr) \
- if (!(expr)) \
- SILC_LOG_ERROR(("SILC_VERIFY %s:%d", __FUNCTION__, __LINE__));
+ if (silc_unlikely(!(expr))) { \
+ SILC_LOG_ERROR(("SILC_VERIFY %s:%s:%d", \
+ __FILE__, __FUNCTION__, __LINE__)); \
+ silc_set_errno_reason_nofail(SILC_ERR_ASSERT, "SILC_VERIFY %s:%s:%d", \
+ __FILE__, __FUNCTION__, __LINE__); \
+ }
#endif /* SILC_DEBUG */
/***/
void *silc_malloc(size_t size)
{
void *addr;
+
if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
- SILC_LOG_ERROR(("Invalid memory allocation, allocation by %x", size));
+ if (size == 0)
+ silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
+ else
+ silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
+ "Allocation by %d", size);
return NULL;
}
+
addr = malloc(size);
if (silc_unlikely(!addr))
- SILC_LOG_ERROR(("System out of memory"));
+ silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
+
return addr;
}
void *silc_calloc(size_t items, size_t size)
{
void *addr;
+
if (silc_unlikely(size * items <= 0 || size * items >= SILC_MAX_ALLOC)) {
- SILC_LOG_ERROR(("Invalid memory allocation, allocation by %x", size));
+ if (size == 0)
+ silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
+ else
+ silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
+ "Allocation by %d", size);
return NULL;
}
+
addr = calloc(items, size);
if (silc_unlikely(!addr))
- SILC_LOG_ERROR(("System out of memory"));
+ silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
+
return addr;
}
{
void *addr;
if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
- SILC_LOG_ERROR(("Invalid memory allocation, allocation by %x", size));
+ if (size == 0)
+ silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
+ else
+ silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
+ "Allocation by %d", size);
return NULL;
}
+
addr = realloc(ptr, size);
if (silc_unlikely(!addr))
- SILC_LOG_ERROR(("System out of memory"));
+ silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
+
return addr;
}
void *silc_memdup(const void *ptr, size_t size)
{
unsigned char *addr;
+
addr = silc_malloc(size + 1);
if (silc_unlikely(!addr)) {
- SILC_LOG_ERROR(("System out of memory"));
+ silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
return NULL;
}
memcpy((void *)addr, ptr, size);
return (void *)addr;
}
+char *silc_strdup(const char *str)
+{
+ return silc_memdup(str, strlen(str));
+}
+
#endif /* !SILC_STACKTRACE */
/* SilcStack aware routines */
***/
void *silc_memdup(const void *ptr, size_t size);
+/****f* silcutil/SilcMemoryAPI/silc_strdup
+ *
+ * SYNOPSIS
+ *
+ * char *silc_strdup(const char *str);
+ *
+ * DESCRIPTION
+ *
+ * Duplicates the string indicated by `str' and returns the duplicated
+ * string. Returns NULL on error.
+ *
+ ***/
+char *silc_strdup(const char *str);
+
#else
#ifndef SILC_DIST_TOOLKIT
#error "The stack trace is not supported in this distribution"
SILC_LOG_DEBUG(("Parsing MIME message"));
- if (!data)
+ if (!data) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
if (!mime) {
mime = silc_mime_alloc();
if (data_len - i >= 2 && tmp[i] == '\r' && tmp[i + 1] == '\n') {
/* Get field */
field = strchr(line, ':');
- if (!field)
+ if (!field) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
field = silc_memdup(line, field - line);
if (!field)
goto err;
/* Get value. Remove whitespaces too. */
value = strchr(line, ':');
- if ((tmp + i) - value < 2)
+ if ((tmp + i) - value < 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
value++;
for (k = 0; k < (tmp + i) - value; k++) {
- if (value[k] == '\r')
+ if (value[k] == '\r') {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
if (value[k] != ' ' && value[k] != '\t')
break;
}
value += k;
- if ((tmp + i) - value < 1)
+ if ((tmp + i) - value < 1) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
value = silc_memdup(value, (tmp + i) - value);
if (!value)
goto err;
/* Get multipart type */
value = strchr(field, '/');
- if (!value)
+ if (!value) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
value++;
if (strchr(field, '"'))
value++;
- if (!strchr(field, ';'))
+ if (!strchr(field, ';')) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
memset(b, 0, sizeof(b));
len = (unsigned int)(strchr(field, ';') - value);
- if (len > sizeof(b) - 1)
+ if (len > sizeof(b) - 1) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
strncpy(b, value, len);
if (strchr(b, '"'))
*strchr(b, '"') = '\0';
SILC_LOG_DEBUG(("Boundary '%s'", value));
memset(b, 0, sizeof(b));
- line = strdup(value);
+ line = silc_strdup(value);
if (strrchr(line, '"')) {
*strrchr(line, '"') = '\0';
silc_snprintf(b, sizeof(b) - 1, "--%s", line + 1);
- mime->boundary = strdup(line + 1);
+ mime->boundary = silc_strdup(line + 1);
} else {
silc_snprintf(b, sizeof(b) - 1, "--%s", line);
- mime->boundary = strdup(line);
+ mime->boundary = silc_strdup(line);
}
silc_free(line);
tmp[k] == '-' && tmp[k + 1] == '-')
if (!memcmp(tmp + k, b, strlen(b)))
break;
- if (k >= data_len)
+ if (k >= data_len) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
/* Remove preceding CRLF */
k -= 2;
SILC_LOG_DEBUG(("Assembling MIME fragments"));
- if (!assembler || !partial)
+ if (!assembler || !partial) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
type = (char *)silc_mime_get_field(partial, "Content-Type");
- if (!type)
+ if (!type) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
/* Get ID */
tmp = strstr(type, "id=");
- if (!tmp)
+ if (!tmp) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
- if (strlen(tmp) <= 4)
+ }
+ if (strlen(tmp) <= 4) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
tmp += 3;
if (*tmp == '"')
tmp++;
- id = strdup(tmp);
+ id = silc_strdup(tmp);
if (strchr(id, ';'))
*strchr(id, ';') = '\0';
if (strrchr(id, '"'))
/* Get fragment number */
tmp = strstr(type, "number=");
- if (!tmp)
+ if (!tmp) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
tmp = strchr(tmp, '=');
- if (strlen(tmp) < 2)
+ if (strlen(tmp) < 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
tmp++;
if (strchr(tmp, ';')) {
- tmp = strdup(tmp);
+ tmp = silc_strdup(tmp);
*strchr(tmp, ';') = '\0';
number = atoi(tmp);
silc_free(tmp);
tmp = strstr(type, "total=");
if (tmp) {
tmp = strchr(tmp, '=');
- if (strlen(tmp) < 2)
+ if (strlen(tmp) < 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
goto err;
+ }
tmp++;
if (strchr(tmp, ';')) {
- tmp = strdup(tmp);
+ tmp = silc_strdup(tmp);
*strchr(tmp, ';') = '\0';
total = atoi(tmp);
silc_free(tmp);
/* The fragment is in the data portion of the partial message */
data = silc_mime_get_data(p, &data_len);
- if (!data)
+ if (!data) {
+ silc_set_errno(SILC_ERR_BAD_ENCODING);
goto err;
+ }
/* Assemble */
if (!compbuf) {
if (!mime || !field || !value)
return;
- silc_hash_table_add(mime->fields, strdup(field), strdup(value));
+ silc_hash_table_add(mime->fields, silc_strdup(field), silc_strdup(value));
}
/* Get field */
silc_snprintf(tmp, sizeof(tmp) - 1, "multipart/%s; boundary=%s", type, boundary);
silc_mime_add_field(mime, "Content-Type", tmp);
silc_free(mime->boundary);
- mime->boundary = strdup(boundary);
+ mime->boundary = silc_strdup(boundary);
if (mime->multiparts)
return;
SilcBool silc_mime_add_multipart(SilcMime mime, SilcMime part)
{
- if (!mime || !mime->multiparts || !part)
+ if (!mime || !mime->multiparts || !part) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
silc_dlist_add(mime->multiparts, part);
return TRUE;
SilcBool silc_mime_is_multipart(SilcMime mime)
{
- if (!mime)
+ if (!mime) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
return mime->multiparts != NULL;
}
SilcDList silc_mime_get_multiparts(SilcMime mime, const char **type)
{
- if (!mime)
+ if (!mime) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
if (type)
*type = (const char *)mime->multitype;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2006 Pekka Riikonen
+ Copyright (C) 1997 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
return hs;
}
-static const char *silc_net_error[] = {
- "Ok",
- "Unknown IP address",
- "Unknown hostname",
- "Destination unreachable",
- "Connection refused",
- "Connection timeout",
- "System out of memory",
- "Unexpected error",
-};
-
-/* Return error as string */
-
-const char *silc_net_get_error_string(SilcNetStatus error)
-{
- if (error < SILC_NET_OK || error > SILC_NET_ERROR)
- return "";
- return silc_net_error[error];
-}
-
/* Accepts a connection from a particular socket */
int silc_net_accept_connection(int sock)
{
- return accept(sock, 0, 0);
+ int ret = accept(sock, 0, 0);
+ if (ret < 0)
+ silc_set_errno_posix(errno);
}
/* Sets a option for a socket. */
int silc_net_set_socket_opt(int sock, int level, int option, int on)
{
- return setsockopt(sock, level, option, (void *)&on, sizeof(on));
+ int ret = setsockopt(sock, level, option, (void *)&on, sizeof(on));
+ if (ret < 0)
+ silc_set_errno_posix(errno);
}
/* Get socket options */
int silc_net_get_socket_opt(int sock, int level, int option,
void *optval, int *opt_len)
{
- return getsockopt(sock, level, option, optval, opt_len);
+ int ret = getsockopt(sock, level, option, optval, opt_len);
+ if (ret < 0)
+ silc_set_errno_posix(errno);
}
/* Checks whether IP address sent as argument is valid IPv4 address. */
char tmp[64];
if (silc_net_gethostbyname(r->input, r->prefer_ipv6, tmp, sizeof(tmp)))
- r->result = strdup(tmp);
+ r->result = silc_strdup(tmp);
silc_schedule_task_add(schedule, 0, silc_net_resolve_completion, r, 0, 1,
SILC_TASK_TIMEOUT);
char tmp[256];
if (silc_net_gethostbyaddr(r->input, tmp, sizeof(tmp)))
- r->result = strdup(tmp);
+ r->result = silc_strdup(tmp);
silc_schedule_task_add(schedule, 0, silc_net_resolve_completion, r, 0, 1,
SILC_TASK_TIMEOUT);
r->context = context;
r->prefer_ipv6 = prefer_ipv6;
r->schedule = schedule;
- r->input = strdup(name);
+ r->input = silc_strdup(name);
silc_thread_create(silc_net_gethostbyname_thread, r, FALSE);
}
r->completion = completion;
r->context = context;
r->schedule = schedule;
- r->input = strdup(addr);
+ r->input = silc_strdup(addr);
silc_thread_create(silc_net_gethostbyaddr_thread, r, FALSE);
}
return NULL;
if (!silc_net_gethostbyname(hostname, TRUE, ip_addr, sizeof(ip_addr)))
- return strdup(hostname);
+ return silc_strdup(hostname);
silc_net_gethostbyaddr(ip_addr, hostname, sizeof(hostname));
- return strdup(hostname);
+ return silc_strdup(hostname);
}
/* Returns local IP address */
if (!silc_net_gethostbyname(hostname, TRUE, ip_addr, sizeof(ip_addr)))
return NULL;
- return strdup(ip_addr);
+ return silc_strdup(ip_addr);
}
***/
typedef struct SilcNetListenerStruct *SilcNetListener;
-/****d* silcutil/SilcNetAPI/SilcNetStatus
- *
- * NAME
- *
- * typedef enum { ... } SilcNetStatus;
- *
- * DESCRIPTION
- *
- * Status to indicate the result of the network operation creation. This
- * type is returned in the SilcNetCallback callback function.
- *
- * SOURCE
- */
-typedef enum {
- SILC_NET_OK, /* Everything Ok */
- SILC_NET_UNKNOWN_IP, /* Unknown IP address */
- SILC_NET_UNKNOWN_HOST, /* Unknown hostname */
- SILC_NET_HOST_UNREACHABLE, /* Destination unreachable */
- SILC_NET_CONNECTION_REFUSED, /* Connection refused */
- SILC_NET_CONNECTION_TIMEOUT, /* Connection timedout */
- SILC_NET_NO_MEMORY, /* System out of memory */
- SILC_NET_ERROR, /* Unknown error */
-} SilcNetStatus;
-/***/
-
/****f* silcutil/SilcNetAPI/SilcNetCallback
*
* SYNOPSIS
*
- * typedef void (*SilcNetCallback)(SilcNetStatus status,
+ * typedef void (*SilcNetCallback)(SilcResult status,
* SilcStream stream, void *context);
*
* DESCRIPTION
* the `stream'.
*
***/
-typedef void (*SilcNetCallback)(SilcNetStatus status,
+typedef void (*SilcNetCallback)(SilcResult status,
SilcStream stream, void *context);
/****f* silcutil/SilcNetAPI/silc_net_tcp_create_listener
const char *remote_ip_addr, int remote_port,
const unsigned char *data, SilcUInt32 data_len);
-/****f* silcutil/SilcNetAPI/silc_net_get_error_string
- *
- * SYNOPSIS
- *
- * const char silc_net_get_error_string(SilcNetStatus error);
- *
- * DESCRIPTION
- *
- * Return `error' as a string.
- *
- ***/
-const char *silc_net_get_error_string(SilcNetStatus error);
-
/****f* silcutil/SilcNetAPI/silc_net_close_connection
*
* SYNOPSIS
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005 - 2006 Pekka Riikonen
+ Copyright (C) 2005 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
unsigned int lookup : 1;
};
+/* Backwards support */
+#define SilcNetStatus SilcResult
+#define silc_net_get_error_string silc_errno_string
+#define SILC_NET_OK SILC_OK
+#define SILC_NET_UNKNOWN_IP SILC_ERR_UNKNOWN_IP
+#define SILC_NET_UNKNOWN_HOST SILC_ERR_UNKNOWN_HOST
+#define SILC_NET_HOST_UNREACHABLE SILC_ERR_UNREACHABLE
+#define SILC_NET_CONNECTION_REFUSED SILC_ERR_REFUSED
+#define SILC_NET_CONNECTION_TIMEOUT SILC_ERR_TIMEOUT
+#define SILC_NET_NO_MEMORY SILC_ERR_OUT_OF_MEMORY
+#define SILC_NET_ERROR SILC_ERR
+
#endif /* SILCNET_I_H */
{
SilcSchedule schedule;
+ /* Initialize Tls, in case it hasn't been done yet */
+ silc_thread_tls_init();
+
stack = silc_stack_alloc(0, stack);
if (!stack)
return NULL;
{
SilcTask task = NULL;
- if (silc_unlikely(!schedule->valid))
+ if (silc_unlikely(!schedule->valid)) {
+ silc_set_errno(SILC_ERR_NOT_VALID);
return NULL;
+ }
SILC_SCHEDULE_LOCK(schedule);
schedule->max_tasks)) {
SILC_LOG_WARNING(("Scheduler task limit reached: cannot add new task"));
task = NULL;
+ silc_set_errno(SILC_ERR_LIMIT);
goto out;
}
ret = TRUE;
}
+ if (ret == FALSE)
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+
return ret;
}
SILC_SCHEDULE_UNLOCK(schedule);
+ if (ret == FALSE)
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+
return ret;
}
SILC_SCHEDULE_UNLOCK(schedule);
+ if (ret == FALSE)
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+
return ret;
}
SILC_SCHEDULE_UNLOCK(schedule);
+ if (ret == FALSE)
+ silc_set_errno(SILC_ERR_NOT_FOUND);
+
return TRUE;
}
{
SilcTaskFd task;
- if (silc_unlikely(!schedule->valid))
+ if (silc_unlikely(!schedule->valid)) {
+ silc_set_errno(SILC_ERR_NOT_VALID);
return FALSE;
+ }
SILC_SCHEDULE_LOCK(schedule);
SilcTaskFd task;
SilcTaskEvent event = 0;
- if (silc_unlikely(!schedule->valid))
+ if (silc_unlikely(!schedule->valid)) {
+ silc_set_errno(SILC_ERR_NOT_VALID);
return 0;
+ }
SILC_SCHEDULE_LOCK(schedule);
if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
/* Internal async host lookup context. */
typedef struct {
SilcSocketStream stream;
- SilcSocketStreamStatus status;
+ SilcResult status;
SilcSocketStreamCallback callback;
SilcAsyncOperation op;
void *context;
return;
}
- if (lookup->status != SILC_SOCKET_OK) {
+ if (lookup->status != SILC_OK) {
SILC_LOG_DEBUG(("Socket stream lookup failed"));
stream->schedule = NULL;
silc_socket_stream_destroy(stream);
silc_net_check_host_by_sock(stream->sock, &stream->hostname, &stream->ip);
if (!stream->ip) {
- lookup->status = SILC_SOCKET_UNKNOWN_IP;
+ lookup->status = SILC_ERR_UNKNOWN_IP;
goto out;
}
if (!stream->hostname && lookup->require_fqdn) {
- lookup->status = SILC_SOCKET_UNKNOWN_HOST;
+ lookup->status = SILC_ERR_UNKNOWN_HOST;
goto out;
}
if (!stream->hostname) {
- stream->hostname = strdup(stream->ip);
+ stream->hostname = silc_strdup(stream->ip);
if (!stream->hostname) {
- lookup->status = SILC_SOCKET_NO_MEMORY;
+ lookup->status = SILC_ERR_OUT_OF_MEMORY;
goto out;
}
}
- lookup->status = SILC_SOCKET_OK;
+ lookup->status = SILC_OK;
out:
silc_schedule_task_add_timeout(schedule, silc_socket_host_lookup_finish,
if (!sock || !schedule) {
SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create"));
if (callback)
- callback(SILC_SOCKET_ERROR, NULL, context);
+ callback(SILC_ERR_INVALID_ARGUMENT, NULL, context);
return NULL;
}
stream = silc_calloc(1, sizeof(*stream));
if (!stream) {
if (callback)
- callback(SILC_SOCKET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
if (!l) {
silc_free(stream);
if (callback)
- callback(SILC_SOCKET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
silc_free(stream);
silc_free(l);
if (callback)
- callback(SILC_SOCKET_ERROR, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
return l->op;
} else {
/* No lookup */
- l->status = SILC_SOCKET_OK;
+ l->status = SILC_OK;
silc_socket_host_lookup_finish(schedule,
silc_schedule_get_context(schedule),
0, 0, l);
if (hostname) {
silc_free(socket_stream->hostname);
- socket_stream->hostname = strdup(hostname);
+ socket_stream->hostname = silc_strdup(hostname);
if (!socket_stream->hostname)
return FALSE;
}
if (ip) {
silc_free(socket_stream->ip);
- socket_stream->ip = strdup(ip);
+ socket_stream->ip = silc_strdup(ip);
if (!socket_stream->ip)
return FALSE;
if (!socket_stream->hostname) {
- socket_stream->hostname = strdup(ip);
+ socket_stream->hostname = silc_strdup(ip);
if (!socket_stream->hostname)
return FALSE;
}
return TRUE;
}
-/* Return socket errno */
-
-int silc_socket_stream_get_error(SilcStream stream)
-{
- SilcSocketStream socket_stream = stream;
-
- if (!SILC_IS_SOCKET_STREAM(socket_stream) &&
- !SILC_IS_SOCKET_STREAM_UDP(socket_stream))
- return 0;
-
- return socket_stream->sock_error;
-}
-
/* Set QoS for socket stream */
SilcBool silc_socket_stream_set_qos(SilcStream stream,
#ifndef SILCSOCKETSTREAM_H
#define SILCSOCKETSTREAM_H
-/****d* silcutil/SilcSocketStreamAPI/SilcSocketStreamStatus
- *
- * NAME
- *
- * typedef enum { ... } SilcStreamStatus;
- *
- * DESCRIPTION
- *
- * Socket Stream status. This status is returned into the
- * SilcSocketStreamCallback function after the socket stream is
- * created.
- *
- * SOURCE
- */
-typedef enum {
- SILC_SOCKET_OK, /* Normal status */
- SILC_SOCKET_UNKNOWN_IP, /* Remote does not have IP address */
- SILC_SOCKET_UNKNOWN_HOST, /* Remote does not have host name */
- SILC_SOCKET_NO_MEMORY, /* System out of memory */
- SILC_SOCKET_ERROR, /* Unknown error */
-} SilcSocketStreamStatus;
-/***/
-
/****f* silcutil/SilcSocketStreamAPI/SilcSocketStreamCallback
*
* SYNOPSIS
*
- * typedef void (*SilcSocketStreamCallback)(SilcSocketStreamStatus status,
+ * typedef void (*SilcSocketStreamCallback)(SilcResult status,
* SilcStream stream,
* void *context);
*
* non-blocking mode.
*
***/
-typedef void (*SilcSocketStreamCallback)(SilcSocketStreamStatus status,
+typedef void (*SilcSocketStreamCallback)(SilcResult status,
SilcStream stream, void *context);
/****f* silcutil/SilcSocketStreamAPI/silc_socket_tcp_stream_create
const char *hostname,
const char *ip, SilcUInt16 port);
-/****f* silcutil/SilcSocketStreamAPI/silc_socket_stream_get_error
- *
- * SYNOPSIS
- *
- * int silc_socket_stream_get_error(SilcStream stream);
- *
- * DESCRIPTION
- *
- * If error occurred during socket stream operations, this function
- * can be used to retrieve the error number that occurred.
- *
- ***/
-int silc_socket_stream_get_error(SilcStream stream);
-
/****f* silcutil/SilcSocketStreamAPI/silc_socket_stream_set_qos
*
* SYNOPSIS
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2005 - 2006 Pekka Riikonen
+ Copyright (C) 2005 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
SilcSocket sock;
char *hostname;
char *ip;
- SilcUInt16 port;
- SilcUInt16 sock_error;
SilcSocketQos qos;
SilcStreamNotifier notifier;
void *notifier_context;
+ SilcUInt16 port;
unsigned int ipv6 : 1; /* UDP IPv6 */
unsigned int connected : 1; /* UDP connected state */
};
extern const SilcStreamOps silc_socket_stream_ops;
extern const SilcStreamOps silc_socket_udp_stream_ops;
+/* Backwards support */
+#define silc_socket_stream_get_error(stream) silc_errno
+#define SILC_SOCKET_OK SILC_OK
+#define SILC_SOCKET_UNKNOWN_IP SILC_ERR_UNKNOWN_IP
+#define SILC_SOCKET_UNKNOWN_HOST SILC_ERR_UNKNOWN_HOST
+#define SILC_SOCKET_NO_MEMORY SILC_ERR_OUT_OF_MEMORY
+#define SILC_SOCKET_ERROR SILC_ERR
+
#endif /* SILCSOCKETSTREAM_I_H */
SILC_ST_DEBUG(("Allocating %d bytes from %p", size, stack));
if (silc_unlikely(!size)) {
- SILC_LOG_ERROR(("Allocation by zero (0)"));
+ SILC_LOG_DEBUG(("Allocation by zero (0)"));
+ silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
SILC_STACK_STAT(stack, num_errors, 1);
return NULL;
}
if (silc_unlikely(size > SILC_STACK_MAX_ALLOC)) {
- SILC_LOG_ERROR(("Allocating too much"));
+ SILC_LOG_DEBUG(("Allocating too much"));
+ silc_set_errno_nofail(SILC_ERR_TOO_LARGE_ALLOCATION);
SILC_STACK_STAT(stack, num_errors, 1);
if (stack->oom_handler)
stack->oom_handler(stack, stack->oom_context);
si++;
}
if (silc_unlikely(si >= SILC_STACK_BLOCK_NUM)) {
- SILC_LOG_ERROR(("Allocating too large block"));
+ SILC_LOG_DEBUG(("Allocating too large block"));
+ silc_set_errno_nofail(SILC_ERR_TOO_LARGE_ALLOCATION);
SILC_STACK_STAT(stack, num_errors, 1);
if (stack->oom_handler)
stack->oom_handler(stack, stack->oom_context);
SILC_ST_DEBUG(("Reallocating %d bytes (%d) from %p", size, old_size, stack));
if (silc_unlikely(!size || !old_size)) {
- SILC_LOG_ERROR(("Allocation by zero (0)"));
+ SILC_LOG_DEBUG(("Allocation by zero (0)"));
+ silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
SILC_STACK_STAT(stack, num_errors, 1);
return NULL;
}
if (silc_unlikely(size > SILC_STACK_MAX_ALLOC)) {
- SILC_LOG_ERROR(("Allocating too much"));
+ SILC_LOG_DEBUG(("Allocating too much"));
+ silc_set_errno_nofail(SILC_ERR_TOO_LARGE_ALLOCATION);
SILC_STACK_STAT(stack, num_errors, 1);
if (stack->oom_handler)
stack->oom_handler(stack, stack->oom_context);
if (stack->stack->data[si]->bytes_left + old_size +
((unsigned char *)ptr - (unsigned char *)sptr) != bsize) {
SILC_LOG_DEBUG(("Cannot reallocate"));
+ silc_set_errno_nofail(SILC_ERR_BAD_ADDRESS);
SILC_STACK_STAT(stack, num_errors, 1);
return NULL;
}
}
SILC_LOG_DEBUG(("Cannot reallocate in this block"));
+ silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
SILC_STACK_STAT(stack, num_errors, 1);
return NULL;
}
typedef enum {
SILC_STREAM_CAN_READ, /* Data available for reading */
SILC_STREAM_CAN_WRITE, /* Stream ready for writing */
- SILC_STREAM_EOS, /* End of stream */
- SILC_STREAM_CLOSED, /* Stream is closed */
- SILC_STREAM_INVALID, /* Stream is invalid */
- SILC_STREAM_NO_MEMORY, /* System out of memory */
- SILC_STREAM_ERROR, /* Unknown error */
} SilcStreamStatus;
/***/
* the notifier callback will later be called with SILC_STREAM_CAN_READ
* status when stream is again ready for reading.
*
+ * If error occurred the error code can be retrieved with silc_errno.
+ *
***/
int silc_stream_read(SilcStream stream, unsigned char *buf,
SilcUInt32 buf_len);
* notifier callback will later be called with SILC_STREAM_CAN_WRITE
* status when stream is again ready for writing.
*
+ * If error occurred the error code can be retrieved with silc_errno.
+ *
***/
int silc_stream_write(SilcStream stream, const unsigned char *data,
SilcUInt32 data_len);
char **splitted = NULL, sep[1], *item, *cp;
int i = 0, len;
- if (!string)
- return NULL;
- if (!ret_count)
+ if (!string || !ret_count) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
splitted = silc_calloc(1, sizeof(*splitted));
if (!splitted)
int i, len, count;
char *regex;
- if (!string)
+ if (!string) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
len = strlen(string);
count = 4;
char *tmp;
int len1, len2;
- if (!string1 || !string2)
+ if (!string1 || !string2) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
len1 = strlen(string1);
len2 = strlen(string2);
regex_t preg;
int ret = FALSE;
- if (regcomp(&preg, regex, REG_NOSUB | REG_EXTENDED) != 0)
+ if (regcomp(&preg, regex, REG_NOSUB | REG_EXTENDED) != 0) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
if (regexec(&preg, string, 0, NULL, 0) == 0)
ret = TRUE;
char *s1;
int ret = FALSE;
- if (!string1 || !string2)
+ if (!string1 || !string2) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return ret;
+ }
s1 = silc_string_regexify(string1);
ret = silc_string_regex_match(s1, string2);
SilcThreadPool tp;
int i;
- if (max_threads < min_threads)
+ if (max_threads < min_threads) {
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT,
+ "Max threads is smaller than min threads (%d < %d)",
+ max_threads, min_threads);
return NULL;
- if (!max_threads)
+ }
+ if (!max_threads) {
+ silc_set_errno_reason(SILC_ERR_INVALID_ARGUMENT, "Max threads is 0");
return NULL;
+ }
if (stack)
stack = silc_stack_alloc(0, stack);
if (tp->destroy) {
silc_mutex_unlock(tp->lock);
+ silc_set_errno(SILC_ERR_NOT_VALID);
return FALSE;
}
/* Maximum threads reached */
if (!queuable) {
silc_mutex_unlock(tp->lock);
+ silc_set_errno(SILC_ERR_LIMIT);
return FALSE;
}
with silc_calloc and freeable with silc_free, and must also be able to
pre-allocate from stack. */
typedef struct SilcTlsObject {
- void *thread_context; /* Context set with SILC Tls API */
- void *platform_context; /* Platform specific context */
+ void *thread_context; /* Context set with SILC Tls API */
+ void *platform_context; /* Platform specific context */
+ char error_reason[256]; /* Reason for the error */
+ SilcResult error; /* Errno, last error */
} *SilcTls, SilcTlsStruct;
/* The internal Tls API. Implementation is platform specific. */
unsigned int msec)
{
if (year > (1 << 15))
- return FALSE;
+ goto err;
if (month < 1 || month > 12)
- return FALSE;
+ goto err;
if (day < 1 || day > 31)
- return FALSE;
+ goto err;
if (hour > 23)
- return FALSE;
+ goto err;
if (minute > 60)
- return FALSE;
+ goto err;
if (second > 61)
- return FALSE;
+ goto err;
if (msec > 1000)
- return FALSE;
+ goto err;
time->year = year;
time->month = month;
time->msecond = msec;
return TRUE;
+
+ err:
+ silc_set_errno(SILC_ERR_BAD_TIME);
+ return FALSE;
}
/* Return time since Epoch */
SilcInt64 silc_time_usec(void)
{
struct timeval curtime;
- silc_gettimeofday(&curtime);
+ if (silc_gettimeofday(&curtime))
+ silc_set_errno_posix(errno);
return (curtime.tv_sec * (SilcUInt64)1000000) + curtime.tv_usec;
}
else
curtime = (time_t)time_val;
return_time = ctime(&curtime);
- if (!return_time)
+ if (!return_time) {
+ silc_set_errno(SILC_ERR_BAD_TIME);
return NULL;
+ }
return_time[strlen(return_time) - 1] = '\0';
return (const char *)return_time;
timeval = (time_t)((SilcUInt64)time_val / (SilcUInt64)1000);
t = localtime(&timeval);
- if (!t)
+ if (!t) {
+ silc_set_errno(SILC_ERR_BAD_TIME);
return FALSE;
+ }
memset(ret_time, 0, sizeof(*ret_time));
if (!silc_time_fill(ret_time, t->tm_year + 1900, t->tm_mon + 1,
{
SilcTimeStruct curtime;
- if (timezone_size < 6)
+ if (timezone_size < 6) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
if (!silc_time_value(0, &curtime))
return FALSE;
&day, &hour, &minute, &second, &z);
if (ret < 3) {
SILC_LOG_DEBUG(("Invalid UTC time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME, "Invalid UTC time string");
return FALSE;
}
ret = sscanf(universal_time + (ret * 2) + 1, "%02u%02u", &hour, &minute);
if (ret != 2) {
SILC_LOG_DEBUG(("Malformed UTC time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME, "Malformed UTC time string");
return FALSE;
}
- if (hour > 23)
- return FALSE;
- if (minute > 60)
+ if (hour > 23 || minute > 60) {
+ silc_set_errno(SILC_ERR_BAD_TIME);
return FALSE;
+ }
ret_time->utc_hour = hour;
ret_time->utc_minute = minute;
ret_time->utc_east = (z == '-') ? 0 : 1;
} else if (z != 'Z') {
SILC_LOG_DEBUG(("Invalid timezone"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME, "Invalid timezone");
return FALSE;
}
SilcUInt32 ret_string_size)
{
int ret, len = 0;
+
memset(ret_string, 0, ret_string_size);
ret = silc_snprintf(ret_string, ret_string_size - 1,
- "%02u%02u%02u%02u%02u%02u",
- time_val->year % 100, time_val->month, time_val->day,
- time_val->hour, time_val->minute, time_val->second);
+ "%02u%02u%02u%02u%02u%02u",
+ time_val->year % 100, time_val->month, time_val->day,
+ time_val->hour, time_val->minute, time_val->second);
if (ret < 0)
return FALSE;
len += ret;
len += ret;
} else {
ret = silc_snprintf(ret_string + len, ret_string_size - 1 - len,
- "%c%02u%02u", time_val->utc_east ? '+' : '-',
- time_val->utc_hour, time_val->utc_minute);
+ "%c%02u%02u", time_val->utc_east ? '+' : '-',
+ time_val->utc_hour, time_val->utc_minute);
if (ret < 0)
return FALSE;
len += ret;
&day, &hour, &minute, &second);
if (ret < 3) {
SILC_LOG_DEBUG(("Invalid generalized time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME, "Invalid generalized time string");
return FALSE;
}
ret = sscanf(generalized_time + i, "%c", &z);
if (ret != 1) {
SILC_LOG_DEBUG(("Malformed generalized time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME,
+ "Malformed generalized time string");
return FALSE;
}
ret = sscanf(generalized_time + i, "%u%n", &msecond, &l);
if (ret != 1) {
SILC_LOG_DEBUG(("Malformed generalized time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME,
+ "Malformed generalized time string");
return FALSE;
}
while (l > 4) {
if (z == '-' || z == '+') {
ret = sscanf(generalized_time + i + 1, "%02u%02u", &hour, &minute);
if (ret != 2) {
- SILC_LOG_DEBUG(("Malformed UTC time string"));
+ SILC_LOG_DEBUG(("Malformed generalized time string"));
+ silc_set_errno_reason(SILC_ERR_BAD_TIME,
+ "Malformed generalized time string");
return FALSE;
}
- if (hour > 23)
- return FALSE;
- if (minute > 60)
+ if (hour > 23 || minute > 60) {
+ silc_set_errno(SILC_ERR_BAD_TIME);
return FALSE;
+ }
ret_time->utc_hour = hour;
ret_time->utc_minute = minute;
int len = 0, ret;
memset(ret_string, 0, ret_string_size);
ret = silc_snprintf(ret_string, ret_string_size - 1,
- "%04u%02u%02u%02u%02u%02u",
- time_val->year, time_val->month, time_val->day, time_val->hour,
- time_val->minute, time_val->second);
+ "%04u%02u%02u%02u%02u%02u",
+ time_val->year, time_val->month,
+ time_val->day, time_val->hour,
+ time_val->minute, time_val->second);
if (ret < 0)
return FALSE;
len += ret;
if (time_val->msecond) {
ret = silc_snprintf(ret_string + len, ret_string_size - 1 - len,
- ".%lu", (unsigned long)time_val->msecond);
+ ".%lu", (unsigned long)time_val->msecond);
if (ret < 0)
return FALSE;
len += ret;
len += ret;
} else {
ret = silc_snprintf(ret_string + len, ret_string_size - 1 - len,
- "%c%02u%02u", time_val->utc_east ? '+' : '-',
- time_val->utc_hour, time_val->utc_minute);
+ "%c%02u%02u", time_val->utc_east ? '+' : '-',
+ time_val->utc_hour, time_val->utc_minute);
if (ret < 0)
return FALSE;
len += ret;
{
return timer->running;
}
-
-#if 0
-void silc_timer_synchronize(SilcTimer timer)
-{
- SilcUInt32 tdiff, cumu, i;
- SilcUInt64 t1, t2, tcumu;
-
- /* Sync normal timer */
- for (i = 0, cumu = 0; i < 5; i++) {
- silc_timer_start(timer);
- silc_timer_stop(timer);
- silc_timer_value(timer, NULL, &tdiff);
- cumu += tdiff;
- }
-
- timer->sync_diff = cumu;
- if (timer->sync_diff > 5)
- timer->sync_diff /= 5;
-
- /* Sync CPU tick count */
- tcumu = 0;
- t1 = silc_timer_tick(timer, FALSE);
- t2 = silc_timer_tick(timer, FALSE);
- tcumu += (t2 - t1);
- t1 = silc_timer_tick(timer, FALSE);
- t2 = silc_timer_tick(timer, FALSE);
- tcumu += (t2 - t1);
- t1 = silc_timer_tick(timer, FALSE);
- t2 = silc_timer_tick(timer, FALSE);
- tcumu += (t2 - t1);
- timer->sync_tdiff = tcumu / 3;
-
- t1 = silc_timer_tick(timer, FALSE);
- t2 = silc_timer_tick(timer, TRUE);
- timer->sync_tdiff += (int)(t2 - t1);
-}
-#endif
#error "Do not include this header directly"
#endif
+/* Timer context */
struct SilcTimerObject {
SilcUInt64 start_sec; /* Start seconds */
SilcUInt64 timer_sec; /* Timer seconds */
{
SilcUInt32 enclen = 0, i, charval = 0;
- if (!bin || !bin_len)
+ if (!bin || !bin_len) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
+ }
if (bin_encoding == SILC_STRING_UTF8) {
if (!silc_utf8_valid(bin, bin_len))
if (!utf8)
return bin_len;
if (bin_len > utf8_size)
- return 0;
+ goto overflow;
memcpy(utf8, bin, bin_len);
return bin_len;
}
for (i = 0; i < bin_len; i++) {
if (bin[i] == '\\') {
if (i + 1 >= bin_len)
- return 0;
+ goto overflow;
/* If escaped character is any of the following no processing is
needed, otherwise it is a hex value and we need to read it. */
cv != '>' && cv != ';' && cv != ' ' && cv != '#') {
unsigned int hexval;
if (i + 2 >= bin_len)
+ goto overflow;
+ if (sscanf(&bin[i + 1], "%02X", &hexval) != 1) {
+ silc_set_errno_posix(errno);
return 0;
- if (sscanf(&bin[i + 1], "%02X", &hexval) != 1)
- return 0;
+ }
if (utf8) {
if (enclen + 1 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen] = (unsigned char)hexval;
}
if (utf8) {
if (enclen + 1 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen] = bin[i];
}
enclen++;
break;
case SILC_STRING_ASCII_ESC:
SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC");
+ silc_set_errno(SILC_ERR_NOT_SUPPORTED);
return 0;
break;
case SILC_STRING_BMP:
if (i + 1 >= bin_len)
- return 0;
+ goto overflow;
SILC_GET16_MSB(charval, bin + i);
i += 1;
break;
case SILC_STRING_BMP_LSB:
if (i + 1 >= bin_len)
- return 0;
+ goto overflow;
SILC_GET16_LSB(charval, bin + i);
i += 1;
break;
case SILC_STRING_UNIVERSAL:
if (i + 3 >= bin_len)
- return 0;
+ goto overflow;
SILC_GET32_MSB(charval, bin + i);
i += 3;
break;
case SILC_STRING_UNIVERSAL_LSB:
if (i + 3 >= bin_len)
- return 0;
+ goto overflow;
SILC_GET32_LSB(charval, bin + i);
i += 3;
break;
case SILC_STRING_PRINTABLE:
case SILC_STRING_VISIBLE:
- if (!isprint(bin[i]))
+ if (!isprint(bin[i])) {
+ silc_set_errno(SILC_ERR_PROHIBITED_CHAR);
return 0;
+ }
charval = bin[i];
break;
case SILC_STRING_NUMERICAL:
- if (bin[i] != 0x20 && !isdigit(bin[i]))
+ if (bin[i] != 0x20 && !isdigit(bin[i])) {
+ silc_set_errno(SILC_ERR_PROHIBITED_CHAR);
return 0;
+ }
charval = bin[i];
break;
default:
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
break;
}
if (charval < 0x80) {
if (utf8) {
if (enclen > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen] = (unsigned char)charval;
}
} else if (charval < 0x800) {
if (utf8) {
if (enclen + 2 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen ] = (unsigned char )(((charval >> 6) & 0x1f) | 0xc0);
utf8[enclen + 1] = (unsigned char )((charval & 0x3f) | 0x80);
} else if (charval < 0x10000) {
if (utf8) {
if (enclen + 3 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen ] = (unsigned char )(((charval >> 12) & 0xf) | 0xe0);
utf8[enclen + 1] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80);
} else if (charval < 0x200000) {
if (utf8) {
if (enclen + 4 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen ] = (unsigned char )(((charval >> 18) & 0x7) | 0xf0);
utf8[enclen + 1] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
} else if (charval < 0x4000000) {
if (utf8) {
if (enclen + 5 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen ] = (unsigned char )(((charval >> 24) & 0x3) | 0xf8);
utf8[enclen + 1] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
} else {
if (utf8) {
if (enclen + 6 > utf8_size)
- return 0;
+ goto overflow;
utf8[enclen ] = (unsigned char )(((charval >> 30) & 0x1) | 0xfc);
utf8[enclen + 1] = (unsigned char )(((charval >> 24) & 0x3f) | 0x80);
}
return enclen;
+
+ overflow:
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return 0;
}
/* Decodes UTF-8 encoded string `utf8' to string of which encoding is
{
SilcUInt32 enclen = 0, i, charval, bytes;
- if (!utf8 || !utf8_len)
+ if (!utf8 || !utf8_len) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
+ }
if (bin_encoding == SILC_STRING_UTF8) {
- if (!silc_utf8_valid(utf8, utf8_len) ||
- utf8_len > bin_size)
+ if (!silc_utf8_valid(utf8, utf8_len))
return 0;
+ if (utf8_len > bin_size)
+ goto overflow;
memcpy(bin, utf8, utf8_len);
return utf8_len;
}
bytes = 1;
} else if ((utf8[i] & 0xe0) == 0xc0) {
if (i + 1 >= utf8_len)
- return 0;
+ goto overflow;
if ((utf8[i + 1] & 0xc0) != 0x80)
- return 0;
+ goto bad_char;
charval = (utf8[i++] & 0x1f) << 6;
charval |= utf8[i] & 0x3f;
bytes = 2;
} else if ((utf8[i] & 0xf0) == 0xe0) {
if (i + 2 >= utf8_len)
- return 0;
+ goto overflow;
if (((utf8[i + 1] & 0xc0) != 0x80) ||
((utf8[i + 2] & 0xc0) != 0x80))
- return 0;
+ goto bad_char;
/* Surrogates not allowed (D800-DFFF) */
if (utf8[i] == 0xed &&
utf8[i + 1] >= 0xa0 && utf8[i + 1] <= 0xbf &&
utf8[i + 2] >= 0x80 && utf8[i + 2] <= 0xbf)
- return 0;
+ goto bad_char;
charval = (utf8[i++] & 0xf) << 12;
charval |= (utf8[i++] & 0x3f) << 6;
charval |= utf8[i] & 0x3f;
if (charval < 0x800)
- return 0;
+ goto bad_char;
bytes = 3;
} else if ((utf8[i] & 0xf8) == 0xf0) {
if (i + 3 >= utf8_len)
- return 0;
+ goto overflow;
if (((utf8[i + 1] & 0xc0) != 0x80) ||
((utf8[i + 2] & 0xc0) != 0x80) ||
((utf8[i + 3] & 0xc0) != 0x80))
- return 0;
+ goto bad_char;
charval = ((SilcUInt32)(utf8[i++] & 0x7)) << 18;
charval |= (utf8[i++] & 0x3f) << 12;
charval |= (utf8[i++] & 0x3f) << 6;
charval |= utf8[i] & 0x3f;
if (charval < 0x10000)
- return 0;
+ goto bad_char;
bytes = 4;
} else if ((utf8[i] & 0xfc) == 0xf8) {
if (i + 4 >= utf8_len)
- return 0;
+ goto overflow;
if (((utf8[i + 1] & 0xc0) != 0x80) ||
((utf8[i + 2] & 0xc0) != 0x80) ||
((utf8[i + 3] & 0xc0) != 0x80) ||
((utf8[i + 4] & 0xc0) != 0x80))
- return 0;
+ goto bad_char;
charval = ((SilcUInt32)(utf8[i++] & 0x3)) << 24;
charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
charval |= (utf8[i++] & 0x3f) << 6;
charval |= utf8[i] & 0x3f;
if (charval < 0x200000)
- return 0;
+ goto bad_char;
bytes = 5;
} else if ((utf8[i] & 0xfe) == 0xfc) {
if (i + 5 >= utf8_len)
- return 0;
+ goto overflow;
if (((utf8[i + 1] & 0xc0) != 0x80) ||
((utf8[i + 2] & 0xc0) != 0x80) ||
((utf8[i + 3] & 0xc0) != 0x80) ||
((utf8[i + 4] & 0xc0) != 0x80) ||
((utf8[i + 5] & 0xc0) != 0x80))
- return 0;
+ goto bad_char;
charval = ((SilcUInt32)(utf8[i++] & 0x1)) << 30;
charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 24;
charval |= (utf8[i++] & 0x3f) << 6;
charval |= utf8[i] & 0x3f;
if (charval < 0x4000000)
- return 0;
+ goto bad_char;
bytes = 6;
} else {
- return 0;
+ goto bad_char;
}
switch (bin_encoding) {
case SILC_STRING_NUMERICAL:
if (bin) {
if (enclen + 1 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = (unsigned char)charval;
}
case SILC_STRING_BMP:
if (bin) {
if (enclen + 2 > bin_size)
- return 0;
+ goto overflow;
SILC_PUT16_MSB(charval, bin + enclen);
}
enclen += 2;
case SILC_STRING_BMP_LSB:
if (bin) {
if (enclen + 2 > bin_size)
- return 0;
+ goto overflow;
SILC_PUT16_LSB(charval, bin + enclen);
}
enclen += 2;
case SILC_STRING_UNIVERSAL:
if (bin) {
if (enclen + 4 > bin_size)
- return 0;
+ goto overflow;
SILC_PUT32_MSB(charval, bin + enclen);
}
enclen += 4;
case SILC_STRING_UNIVERSAL_LSB:
if (bin) {
if (enclen + 4 > bin_size)
- return 0;
+ goto overflow;
SILC_PUT32_LSB(charval, bin + enclen);
}
enclen += 4;
if (!enclen && (cv == '#' || cv == ' ')) {
if (bin) {
if (enclen + 2 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = '\\';
bin[enclen + 1] = cv;
}
if (i == utf8_len - 1 && cv == ' ') {
if (bin) {
if (enclen + 2 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = '\\';
bin[enclen + 1] = cv;
}
cv == '>' || cv == ';') {
if (bin) {
if (enclen + 2 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = '\\';
bin[enclen + 1] = cv;
}
if (!isprint((int)cv)) {
if (bin) {
if (enclen + 3 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = '\\';
silc_snprintf(bin + enclen + 1, 3, "%02X", cv);
}
if (bin) {
if (enclen + 1 > bin_size)
- return 0;
+ goto overflow;
bin[enclen] = cv;
}
enclen++;
}
break;
default:
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
break;
}
}
return enclen;
+
+ overflow:
+ silc_set_errno(SILC_ERR_OVERFLOW);
+ return 0;
+
+ bad_char:
+ silc_set_errno(SILC_ERR_BAD_CHAR_ENCODING);
+ return 0;
}
/* UTF-8 to wide characters */
if (!tmp_len)
return 0;
- if (utf8_wide_size < tmp_len / 2)
+ if (utf8_wide_size < tmp_len / 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return 0;
+ }
memset(utf8_wide, 0, utf8_wide_size * 2);
SilcUInt32 tmp_len;
int i, k;
- if (utf8_size < wide_str_len * 2)
+ if (utf8_size < wide_str_len * 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return 0;
+ }
memset(utf8, 0, utf8_size);
i = 0;
for ( ; start <= srclen; i++, start++) {
- if (i > destlen)
+ if (i > destlen) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return -1;
+ }
dest[i] = src[start];
- if (dest[i] == EOF)
+ if (dest[i] == EOF) {
+ silc_set_errno(SILC_ERR_EOF);
return EOF;
+ }
if (dest[i] == '\n')
break;
return start;
}
-/* Checks line for illegal characters. Return -1 when illegal character
- were found. This is used to check for bad lines when reading data from
- for example a configuration file. */
-
-int silc_check_line(char *buf)
-{
- /* Illegal characters in line */
- if (strchr(buf, '#')) return -1;
- if (strchr(buf, '\'')) return -1;
- if (strchr(buf, '\\')) return -1;
- if (strchr(buf, '\r')) return -1;
- if (strchr(buf, '\a')) return -1;
- if (strchr(buf, '\b')) return -1;
- if (strchr(buf, '\f')) return -1;
-
- /* Empty line */
- if (buf[0] == '\n')
- return -1;
-
- return 0;
-}
-
/* Converts string to capital characters. */
SilcBool silc_to_upper(const char *string, char *dest, SilcUInt32 dest_size)
{
int i;
- if (strlen(string) > dest_size)
+ if (strlen(string) > dest_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
for (i = 0; i < strlen(string); i++)
dest[i] = (char)toupper((int)string[i]);
{
int i;
- if (strlen(string) > dest_size)
+ if (strlen(string) > dest_size) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
for (i = 0; i < strlen(string); i++)
dest[i] = (char)tolower((int)string[i]);
{
SilcUInt32 tlen;
- if (!user && !fqdn)
+ if (!user && !fqdn) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
+ }
memset(user, 0, user_size);
memset(fqdn, 0, fqdn_size);
- if (!string)
+ if (!string) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return 0;
+ }
if (string[0] == '@') {
if (user)
silc_vsnprintf(buf, sizeof(buf) - 1, fmt, args);
va_end(args);
- return strdup(buf);
+ return silc_strdup(buf);
}
/* Basic has function to hash strings. May be used with the SilcHashTable.
if ((i + 1) % 10 == 0)
cp[-1] = 0;
- return strdup(fingerprint);
+ return silc_strdup(fingerprint);
}
/* Return TRUE if the `data' is ASCII string. */
fd = open("/dev/tty", O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "silc: %s\n", strerror(errno));
+ silc_set_errno_posix(errno);
return NULL;
}
fflush(stdout);
if ((read(fd, input, sizeof(input))) < 0) {
- fprintf(stderr, "silc: %s\n", strerror(errno));
+ silc_set_errno_posix(errno);
tcsetattr(fd, TCSANOW, &to_old);
return NULL;
}
if (strlen(input) <= 1) {
tcsetattr(fd, TCSANOW, &to_old);
+ silc_set_errno(SILC_ERR_EOF);
return NULL;
}
} else {
fd = open("/dev/tty", O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "silc: %s\n", strerror(errno));
+ silc_set_errno_posix(errno);
return NULL;
}
fflush(stdout);
if ((read(fd, input, sizeof(input))) < 0) {
- fprintf(stderr, "silc: %s\n", strerror(errno));
+ silc_set_errno_posix(errno);
return NULL;
}
- if (strlen(input) <= 1)
+ if (strlen(input) <= 1) {
+ silc_set_errno(SILC_ERR_EOF);
return NULL;
+ }
if (strchr(input, '\n'))
*strchr(input, '\n') = '\0';
- return strdup(input);
+ return silc_strdup(input);
}
#else
return NULL;
unsigned char l, h;
int i;
- if (data_size < strlen(hex) / 2)
+ if (data_size < strlen(hex) / 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
for (i = 0; i < strlen(hex) / 2; i++) {
h = *cp++;
char *cp = hex;
int i;
- if (hex_size - 1 < data_len * 2)
+ if (hex_size - 1 < data_len * 2) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
memset(hex, 0, hex_size);
***/
int silc_gets(char *dest, int destlen, const char *src, int srclen, int begin);
-/****f* silcutil/SilcUtilAPI/silc_check_line
- *
- * SYNOPSIS
- *
- * int silc_check_line(char *buf);
- *
- * DESCRIPTION
- *
- * Checks line for illegal characters. Return -1 when illegal character
- * were found. This is used to check for bad lines when reading data from
- * for example a configuration file.
- *
- ***/
-int silc_check_line(char *buf);
-
/****f* silcutil/SilcUtilAPI/silc_to_upper
*
* SYNOPSIS
/* Deliver new stream to upper layer */
-static void silc_net_accept_stream(SilcSocketStreamStatus status,
+static void silc_net_accept_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetListener listener = (SilcNetListener)context;
/* In case of error, the socket has been destroyed already via
silc_stream_destroy. */
- if (status != SILC_SOCKET_OK)
+ if (status != SILC_OK)
return;
- listener->callback(SILC_NET_OK, stream, listener->context);
+ listener->callback(SILC_OK, stream, listener->context);
}
} /* extern "C" */
listener = (SilcNetListener)silc_calloc(1, sizeof(*listener));
if (!listener) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
listener->schedule = schedule;
listener->socks = (SilcSocket *)silc_calloc(local_ip_count,
sizeof(*listener->socks));
if (!listener->socks) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
} else {
listener->socks = (SilcSocket *)silc_calloc(1, sizeof(*listener->socks));
if (!listener->socks) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
if (l)
delete l;
if (callback)
- callback(SILC_NET_ERROR, NULL, context);
+ callback(SILC_ERR, NULL, context);
if (listener)
silc_net_close_listener(listener);
return NULL;
listener = (SilcNetListener)silc_calloc(1, sizeof(*listener));
if (!listener) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
listener->schedule = schedule;
listener->socks = (SilcSocket *)silc_calloc(port_count,
sizeof(*listener->socks));
if (!listener->socks) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
} else {
listener->socks = (SilcSocket *)silc_calloc(1, sizeof(*listener->socks));
if (!listener->socks) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
if (l)
delete l;
if (callback)
- callback(SILC_NET_ERROR, NULL, context);
+ callback(SILC_ERR, NULL, context);
if (listener)
silc_net_close_listener(listener);
return NULL;
/**************************** TCP/IP connecting *****************************/
-static void silc_net_connect_stream(SilcSocketStreamStatus status,
- SilcStream stream, void *context);
+static void silc_net_connect_stream(SilcResult status,
+ SilcStream stream, void *context);
} /* extern "C" */
if (iStatus != KErrNone) {
if (callback)
- callback(SILC_NET_ERROR, NULL, context);
+ callback(SILC_ERR, NULL, context);
sock->CancelConnect();
delete sock;
ss->Close();
/* TCP stream creation callback */
-static void silc_net_connect_stream(SilcSocketStreamStatus status,
+static void silc_net_connect_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcSymbianTCPConnect *conn = (SilcSymbianTCPConnect *)context;
- SilcNetStatus net_status = SILC_NET_OK;
SILC_LOG_DEBUG(("Socket stream creation status %d", status));
- if (status != SILC_SOCKET_OK) {
- /* In case of error, the socket has been destroyed already via
- silc_stream_destroy. */
- if (status == SILC_SOCKET_UNKNOWN_IP)
- net_status = SILC_NET_UNKNOWN_IP;
- else if (status == SILC_SOCKET_UNKNOWN_HOST)
- net_status = SILC_NET_UNKNOWN_HOST;
- else
- net_status = SILC_NET_ERROR;
- }
-
/* Call connection callback */
if (conn->callback)
- conn->callback(net_status, stream, conn->context);
+ conn->callback(status, stream, conn->context);
else if (stream)
silc_stream_destroy(stream);
{
SilcSymbianTCPConnect *conn;
TInetAddr local, remote;
- SilcNetStatus status;
+ SilcResult status;
TInt ret;
if (!remote_ip_addr || remote_port < 1 || !schedule || !callback)
conn = new SilcSymbianTCPConnect;
if (!conn) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
conn->schedule = schedule;
conn->port = remote_port;
conn->remote = strdup(remote_ip_addr);
if (!conn->remote) {
- status = SILC_NET_NO_MEMORY;
+ status = SILC_ERR_OUT_OF_MEMORY;
goto err;
}
/* Allocate socket */
conn->sock = new RSocket;
if (!conn->sock) {
- status = SILC_NET_NO_MEMORY;
+ status = SILC_ERR_OUT_OF_MEMORY;
goto err;
}
/* Allocate socket server */
conn->ss = new RSocketServ;
if (!conn->ss) {
- status = SILC_NET_NO_MEMORY;
+ status = SILC_ERR_OUT_OF_MEMORY;
goto err;
}
ret = conn->ss->Connect();
if (ret != KErrNone) {
SILC_LOG_ERROR(("Error connecting to socket server, error %d", ret));
- status = SILC_NET_ERROR;
+ status = SILC_ERR;
goto err;
}
/* Start async operation */
conn->op = silc_async_alloc(silc_net_connect_abort, NULL, (void *)conn);
if (!conn->op) {
- status = SILC_NET_NO_MEMORY;
+ status = SILC_ERR_OUT_OF_MEMORY;
goto err;
}
sizeof(conn->remote_ip))) {
SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the "
"host", conn->remote));
- status = SILC_NET_HOST_UNREACHABLE;
+ status = SILC_ERR_UNREACHABLE;
goto err;
}
ret = conn->sock->Open(*conn->ss, KAfInet, KSockStream, KProtocolInetTcp);
if (ret != KErrNone) {
SILC_LOG_ERROR(("Cannot create socket, error %d", ret));
- status = SILC_NET_ERROR;
+ status = SILC_ERR;
goto err;
}
/* Connect to the host */
if (!silc_net_set_sockaddr(&remote, conn->remote_ip, remote_port)) {
SILC_LOG_ERROR(("Cannot connect (cannot set address)"));
- status = SILC_NET_ERROR;
+ status = SILC_ERR;
goto err;
}
conn->Connect(remote);
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*async*");
+ silc_log_set_debug_string("*async*,*errno*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*atomic*");
+ silc_log_set_debug_string("*atomic*,*errno*");
}
silc_atomic_init8(&ref8, 1);
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*bit*");
+ silc_log_set_debug_string("*bit*,*err*");
}
silc_bit_clear_bitmap(bitmap, size);
SILC_LOG_DEBUG(("Test overflow"));
if (silc_bit_set(bitmap, size, 1500))
goto err;
- SILC_LOG_DEBUG(("Overflow detected"));
+ if (silc_errno == SILC_ERR_OVERFLOW)
+ SILC_LOG_DEBUG(("Overflow detected"));
SILC_LOG_DEBUG(("Find first set bit"));
bit = silc_bit_ffs(bitmap, size);
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*dll*");
+ silc_log_set_debug_string("*dll*,*errno*");
}
SILC_LOG_DEBUG(("Load shared object /lib/libc.so.6"));
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*env*");
+ silc_log_set_debug_string("*env*,*errno*");
}
silc_setenv("FOO", "BAR");
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*fdstream*");
+ silc_log_set_debug_string("*fdstream*,*errno*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
silc_log_quick(TRUE);
- silc_log_set_debug_string("*fsm*,*async*");
+ silc_log_set_debug_string("*fsm*,*async*,*errno*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
silc_log_quick(TRUE);
- silc_log_set_debug_string("*table*");
+ silc_log_set_debug_string("*table*,*errno*");
}
if (argc > 1 && !strcmp(argv[1], "-D")) {
silc_log_debug(TRUE);
dump = TRUE;
- silc_log_set_debug_string("*table*");
+ silc_log_set_debug_string("*table*,*errno*");
}
if (!alloc_table())
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*list*");
+ silc_log_set_debug_string("*list*,*errno*");
}
silc_list_init_prev(list, struct foo, next, prev);
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*mime*");
+ silc_log_set_debug_string("*mime*,*errno*");
}
/*
SilcFSMThreadStruct thread;
SilcNetListener server;
SilcStream client_stream;
- SilcNetStatus client_status;
+ SilcResult client_status;
SilcStream server_stream;
- SilcNetStatus server_status;
+ SilcResult server_status;
SilcBool success;
} *Foo;
SILC_FSM_STATE(test_st_connect);
SILC_FSM_STATE(test_st_connected);
-static void test_accept_connection(SilcNetStatus status, SilcStream stream,
+static void test_accept_connection(SilcResult status, SilcStream stream,
void *context)
{
Foo f = context;
SILC_FSM_EVENT_SIGNAL(&f->sema);
}
-static void test_connected(SilcNetStatus status, SilcStream stream,
+static void test_connected(SilcResult status, SilcStream stream,
void *context)
{
Foo f = context;
SILC_LOG_DEBUG(("test_st_connected"));
- if (f->server_status != SILC_NET_OK) {
+ if (f->server_status != SILC_OK) {
SILC_LOG_DEBUG(("Creating connection failed"));
return SILC_FSM_FINISH;
}
SILC_FSM_EVENT_WAIT(&f->sema);
- if (f->client_status != SILC_NET_OK) {
+ if (f->client_status != SILC_OK) {
/** Accepting new connection failed */
SILC_LOG_DEBUG(("Accepting failed %d", f->client_status));
silc_fsm_next(fsm, test_st_finish);
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*net*,*stream*");
+ silc_log_set_debug_string("*net*,*stream*,*errno*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*sched*,*hash*");
+ silc_log_set_debug_string("*sched*,*hash*,*errno*");
}
SILC_LOG_DEBUG(("Allocating scheduler"));
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
silc_log_quick(TRUE);
- silc_log_set_debug_string("*stack*");
+ silc_log_set_debug_string("*stack*,*errno*");
}
SILC_LOG_DEBUG(("Allocating stack of default size (1024 bytes)"));
silc_log_debug(TRUE);
silc_log_debug_hexdump(TRUE);
silc_log_quick(TRUE);
- silc_log_set_debug_string("*stringprep*,*utf8*");
+ silc_log_set_debug_string("*stringprep*,*utf8*,*errno*");
}
SILC_LOG_DEBUG(("--- Identifier string tests"));
if (optarg)
silc_log_set_debug_string(optarg);
else
- silc_log_set_debug_string("*strutil*");
+ silc_log_set_debug_string("*strutil*,*errno*");
break;
default:
exit(1);
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*thread*");
+ silc_log_set_debug_string("*thread*,*errno*");
}
schedule = silc_schedule_init(0, NULL, NULL);
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*time*");
+ silc_log_set_debug_string("*time*,*errno*");
}
SILC_LOG_DEBUG(("Get current time"));
silc_log_debug(TRUE);
silc_log_quick(TRUE);
silc_log_debug_hexdump(TRUE);
- silc_log_set_debug_string("*timer*");
+ silc_log_set_debug_string("*timer*,*errno*");
}
schedule = silc_schedule_init(0, NULL, NULL);
if (ip_addr) {
if (!silc_net_is_ip(ip_addr)) {
SILC_LOG_ERROR(("%s is not IP address", ip_addr));
+ silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address",
+ ip_addr);
return FALSE;
}
if (silc_net_is_ip4(ip_addr)) {
/* IPv4 address */
len = sizeof(addr->sin.sin_addr);
- silc_net_addr2bin(ip_addr,
- (unsigned char *)&addr->sin.sin_addr.s_addr, len);
+ if (!silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin.sin_addr.s_addr, len))
+ return FALSE;
addr->sin.sin_family = AF_INET;
addr->sin.sin_port = port ? htons(port) : 0;
} else {
#ifdef HAVE_IPV6
/* IPv6 address */
len = sizeof(addr->sin6.sin6_addr);
- silc_net_addr2bin(ip_addr,
- (unsigned char *)&addr->sin6.sin6_addr, len);
+ if (!silc_net_addr2bin(ip_addr,
+ (unsigned char *)&addr->sin6.sin6_addr, len))
+ return FALSE;
addr->sin6.sin6_family = AF_INET6;
addr->sin6.sin6_port = port ? htons(port) : 0;
#else
SILC_LOG_ERROR(("IPv6 support is not compiled in"));
+ silc_set_errno(SILC_ERR_NOT_SUPPORTED);
return FALSE;
#endif
}
/* Deliver new stream to upper layer */
-static void silc_net_accept_stream(SilcSocketStreamStatus status,
+static void silc_net_accept_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetListener listener = context;
- if (status != SILC_SOCKET_OK)
+ if (status != SILC_OK)
return;
- listener->callback(SILC_NET_OK, stream, listener->context);
+ listener->callback(SILC_OK, stream, listener->context);
}
/* Accept incoming connection and notify upper layer */
SILC_LOG_DEBUG(("Creating TCP listener"));
- if (port < 0 || !schedule || !callback)
+ if (port < 0 || !schedule || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
listener = silc_calloc(1, sizeof(*listener));
if (!listener)
/* Create the socket */
sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
if (sock < 0) {
- SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
/* Bind the listener socket */
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot bind socket: %s",
+ silc_errno_string(silc_errno)));
close(sock);
goto err;
}
/* Specify that we are listenning */
rval = listen(sock, 64);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot set socket listenning: %s",
+ silc_errno_string(silc_errno)));
close(sock);
goto err;
}
SILC_LOG_DEBUG(("Creating TCP listener"));
- if (!schedule || !callback)
+ if (!schedule || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
listener = silc_calloc(1, sizeof(*listener));
if (!listener)
if (sock < 0) {
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
close(sock);
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
close(sock);
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot bind socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot bind socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
rval = listen(sock, 64);
if (rval < 0) {
close(sock);
- SILC_LOG_ERROR(("Cannot set socket listenning: %s", strerror(errno)));
if (ignore_port_error)
continue;
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot set socket listenning: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
SILC_LOG_DEBUG(("Creating UDP stream"));
- if (!schedule)
+ if (!schedule) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
/* Bind to local addresses */
SILC_LOG_DEBUG(("Binding to local address %s",
/* Create the socket */
sock = socket(server.sin.sin_family, SOCK_DGRAM, 0);
if (sock < 0) {
- SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Cannot create socket: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
/* Set the socket options */
rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
#ifdef SO_REUSEPORT
rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEPORT, 1);
if (rval < 0) {
- SILC_LOG_ERROR(("Cannot set socket options: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot set socket options: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
#endif /* SO_REUSEPORT */
/* Bind the listener socket */
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_DEBUG(("Cannot bind socket: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_DEBUG(("Cannot bind socket: %s", silc_errno_string(silc_errno)));
goto err;
}
rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval < 0) {
- SILC_LOG_DEBUG(("Cannot connect UDP stream: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_DEBUG(("Cannot connect UDP stream: %s",
+ silc_errno_string(silc_errno)));
goto err;
}
}
len = recv(sock->sock, ret_data, data_size, 0);
if (len < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
SILC_LOG_DEBUG(("Cannot read from UDP socket: %d:%s",
sock->sock, strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
ret = sendto(sock->sock, data, data_len, 0, &remote.sa,
SIZEOF_SOCKADDR(remote));
if (ret < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not send immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
/* Asynchronous TCP/IP connecting */
typedef struct {
- SilcNetStatus status;
- SilcSocketStreamStatus stream_status;
+ SilcResult status;
SilcStream stream;
SilcFSMStruct fsm;
SilcFSMEventStruct event;
"host", conn->remote));
/** Network unreachable */
- conn->status = SILC_NET_HOST_UNREACHABLE;
+ conn->status = SILC_ERR_UNREACHABLE;
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
}
/** Cannot create socket */
+ silc_set_errno_posix(errno);
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
if (rval < 0) {
if (errno != EINPROGRESS) {
+ silc_set_errno_posix(errno);
shutdown(sock, 2);
close(sock);
}
/** Cannot connect to remote host */
- SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
+ SILC_LOG_ERROR(("Cannot connect to remote host: %s",
+ silc_errno_string(silc_errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
return SILC_FSM_CONTINUE;
}
-static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
+static void silc_net_connect_wait_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetConnect conn = context;
conn->sop = NULL;
- conn->stream_status = status;
+ conn->status = status;
conn->stream = stream;
SILC_FSM_CALL_CONTINUE(&conn->fsm);
}
return SILC_FSM_CONTINUE;
}
-#if defined(ECONNREFUSED)
- if (opt == ECONNREFUSED)
- conn->status = SILC_NET_CONNECTION_REFUSED;
-#endif /* ECONNREFUSED */
-#if defined(ETIMEDOUT)
- if (opt == ETIMEDOUT)
- conn->status = SILC_NET_CONNECTION_TIMEOUT;
-#endif /* ETIMEDOUT */
-#if defined(ENETUNREACH)
- if (opt == ENETUNREACH)
- conn->status = SILC_NET_HOST_UNREACHABLE;
-#endif /* ENETUNREACH */
+ /* Set error */
+ silc_set_errno_posix(opt);
+ conn->status = silc_errno;
/** Connecting failed */
- SILC_LOG_DEBUG(("Connecting failed, error %s", strerror(opt)));
+ SILC_LOG_DEBUG(("Connecting failed, error %s",
+ silc_errno_string(silc_errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
return SILC_FSM_CONTINUE;
}
- if (conn->stream_status != SILC_SOCKET_OK) {
+ if (conn->status != SILC_OK) {
/** Stream creation failed */
- if (conn->stream_status == SILC_SOCKET_UNKNOWN_IP)
- conn->status = SILC_NET_UNKNOWN_IP;
- else if (conn->stream_status == SILC_SOCKET_UNKNOWN_HOST)
- conn->status = SILC_NET_UNKNOWN_HOST;
- else
- conn->status = SILC_NET_ERROR;
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
/** Stream created successfully */
SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
- conn->status = SILC_NET_OK;
+ conn->status = SILC_OK;
silc_fsm_next(fsm, silc_net_connect_st_finish);
return SILC_FSM_CONTINUE;
}
conn = silc_calloc(1, sizeof(*conn));
if (!conn) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
if (!conn->op) {
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
if (local_ip_addr)
- conn->local_ip = strdup(local_ip_addr);
- conn->remote = strdup(remote_ip_addr);
+ conn->local_ip = silc_strdup(local_ip_addr);
+ conn->remote = silc_strdup(remote_ip_addr);
if (!conn->remote) {
silc_async_free(conn->op);
silc_free(conn->local_ip);
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(silc_errno, NULL, context);
return NULL;
}
conn->port = remote_port;
conn->callback = callback;
conn->context = context;
conn->retry = 1;
- conn->status = SILC_NET_ERROR;
+ conn->status = SILC_ERR;
silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
silc_fsm_start(&conn->fsm, silc_net_connect_st_start);
int silc_net_set_socket_nonblock(SilcSocket sock)
{
- return fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
+ int ret = fcntl((int)sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
+ if (ret)
+ silc_set_errno_posix(errno);
+ return ret;
}
/* Converts the IP number string from numbers-and-dots notation to
if (silc_net_is_ip4(addr)) {
/* IPv4 address */
struct in_addr tmp;
+
+ if (bin_len < 4) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+ return FALSE;
+ }
+
ret = inet_aton(addr, &tmp);
- if (bin_len < 4)
+ if (!ret) {
+ silc_set_errno_posix(errno);
return FALSE;
+ }
memcpy(bin, (unsigned char *)&tmp.s_addr, 4);
#ifdef HAVE_IPV6
SilcSockaddr *s;
/* IPv6 address */
- if (bin_len < 16)
+ if (bin_len < 16) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
if (!sock->qos) {
len = read(sock->sock, buf, buf_len);
if (len < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
SILC_LOG_DEBUG(("Cannot read from socket: %d:%s",
sock->sock, strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
sock->qos->read_limit_bytes);
len = read(sock->sock, qosbuf, len);
if (len < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
silc_schedule_task_del_by_context(sock->schedule, sock->qos);
sock->qos->data_len = 0;
- sock->sock_error = errno;
return -2;
}
ret = write(sock->sock, data, data_len);
if (ret < 0) {
+ silc_set_errno_posix(errno);
if (errno == EAGAIN || errno == EINTR) {
SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot write to socket: %s", strerror(errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = errno;
return -2;
}
return silc_socket_stream_write(stream, data, data_len);
}
-#if 0
-/* Returns human readable socket error message */
-
-SilcBool silc_socket_get_error(SilcStream sock, char *error,
- SilcUInt32 error_len)
-{
- char *err;
-
- if (!sock->sock_error)
- return FALSE;
-
- err = strerror(sock->sock_error);
- if (strlen(err) > error_len)
- return FALSE;
-
- memset(error, 0, error_len);
- memcpy(error, err, strlen(err));
- return TRUE;
-}
-#endif
-
/* Closes socket */
SilcBool silc_socket_stream_close(SilcStream stream)
c->context = context;
if (pthread_attr_init(&attr)) {
- SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Thread error: %s", silc_errno_string(silc_errno)));
silc_free(c);
return NULL;
}
if (pthread_attr_setdetachstate(&attr,
waitable ? PTHREAD_CREATE_JOINABLE :
PTHREAD_CREATE_DETACHED)) {
- SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Thread error: %s", silc_errno_string(silc_errno)));
pthread_attr_destroy(&attr);
silc_free(c);
return NULL;
ret = pthread_create(&thread, &attr, silc_thread_start, c);
if (ret) {
- SILC_LOG_ERROR(("Thread error: %s", strerror(errno)));
+ silc_set_errno_posix(errno);
+ SILC_LOG_ERROR(("Thread error: %s", silc_errno_string(silc_errno)));
pthread_attr_destroy(&attr);
silc_free(c);
return NULL;
*mutex = silc_calloc(1, sizeof(**mutex));
if (*mutex == NULL)
return FALSE;
- pthread_mutex_init(&(*mutex)->mutex, NULL);
+ if (pthread_mutex_init(&(*mutex)->mutex, NULL)) {
+ silc_set_errno_posix(errno);
+ silc_free(*mutex);
+ return FALSE;
+ }
(*mutex)->locked = FALSE;
return TRUE;
#else
*rwlock = silc_calloc(1, sizeof(**rwlock));
if (*rwlock == NULL)
return FALSE;
- pthread_rwlock_init(&(*rwlock)->rwlock, NULL);
+ if (pthread_rwlock_init(&(*rwlock)->rwlock, NULL)) {
+ silc_set_errno_posix(errno);
+ silc_free(*rwlock);
+ return FALSE;
+ }
return TRUE;
#else
return FALSE;
*cond = silc_calloc(1, sizeof(**cond));
if (*cond == NULL)
return FALSE;
- pthread_cond_init(&(*cond)->cond, NULL);
+ if (pthread_cond_init(&(*cond)->cond, NULL)) {
+ silc_set_errno_posix(errno);
+ silc_free(*cond);
+ return FALSE;
+ }
return TRUE;
#else
return FALSE;
defined(HAVE_PTHREAD_ONCE))
static pthread_key_t key;
-static pthread_once_t key_once;
+static pthread_once_t key_once = PTHREAD_ONCE_INIT;
static void silc_thread_tls_destructor(void *context)
{
{
#if defined(HAVE_CLOCK_GETTIME)
struct timespec tp;
- clock_gettime(CLOCK_REALTIME, &tp);
+ if (clock_gettime(CLOCK_REALTIME, &tp))
+ return -1;
p->tv_sec = tp.tv_sec;
p->tv_usec = tp.tv_nsec / 1000;
return 0;
if (ip_addr) {
if (!silc_net_is_ip(ip_addr)) {
SILC_LOG_ERROR(("%s is not IP address", ip_addr));
+ silc_set_errno_reason(SILC_ERR_BAD_IP, "%s is not an IP address",
+ ip_addr);
return FALSE;
}
/* Deliver new stream to upper layer */
-static void silc_net_accept_stream(SilcSocketStreamStatus status,
+static void silc_net_accept_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetListener listener = context;
- if (status != SILC_SOCKET_OK)
+ if (status != SILC_OK)
return;
- listener->callback(SILC_NET_OK, stream, listener->context);
+ listener->callback(SILC_OK, stream, listener->context);
}
/* Accept incoming connection and notify upper layer */
SILC_LOG_DEBUG(("Creating TCP listener"));
- if (port < 0 || !schedule || !callback)
+ if (port < 0 || !schedule || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
listener = silc_calloc(1, sizeof(*listener));
if (!listener)
/* Create the socket */
sock = socket(server.sin.sin_family, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
- SILC_LOG_ERROR(("Cannot create socket, error %d", WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot create socket, error %s",
+ silc_errno_string(silc_errno)));
goto err;
}
/* Set the socket options */
rval = silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
if (rval == SOCKET_ERROR) {
- SILC_LOG_ERROR(("Cannot set socket options, error %d",
- WSAGetLastError()));
+ SILC_LOG_ERROR(("Cannot set socket options, error %s",
+ silc_errno_string(silc_errno)));
closesocket(sock);
goto err;
}
/* Bind the listener socket */
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval == SOCKET_ERROR) {
- SILC_LOG_ERROR(("Cannot bind socket, error %d", WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot bind socket, error %s",
+ silc_errno_string(silc_errno)));
closesocket(sock);
goto err;
}
/* Specify that we are listenning */
rval = listen(sock, SOMAXCONN);
if (rval == SOCKET_ERROR) {
- SILC_LOG_ERROR(("Cannot set socket listenning, error %d",
- WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot set socket listenning, error %s",
+ silc_errno_string(silc_errno)));
closesocket(sock);
goto err;
}
SILC_LOG_DEBUG(("Creating TCP listener"));
- if (!schedule || !callback)
+ if (!schedule || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
goto err;
+ }
listener = silc_calloc(1, sizeof(*listener));
if (!listener)
if (sock == INVALID_SOCKET) {
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot create socket, error %d", WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot create socket, error %s",
+ silc_errno_string(silc_errno)));
goto err;
}
closesocket(sock);
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot set socket options, error %d",
- WSAGetLastError()));
+ SILC_LOG_ERROR(("Cannot set socket options, error %s",
+ silc_errno_string(silc_errno)));
goto err;
}
closesocket(sock);
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot bind socket, error %d", WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot bind socket, error %s",
+ silc_errno_string(silc_errno)));
goto err;
}
closesocket(sock);
if (ignore_port_error)
continue;
- SILC_LOG_ERROR(("Cannot set socket listenning, error %d",
- WSAGetLastError()));
+ silc_set_errno_posix(WSAGetLastError());
+ SILC_LOG_ERROR(("Cannot set socket listenning, error %s",
+ silc_errno_string(silc_errno)));
goto err;
}
sock = socket(server.sin.sin_family, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
SILC_LOG_ERROR(("Cannot create socket"));
+ silc_set_errno_posix(WSAGetLastError());
goto err;
}
rval = bind(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval == SOCKET_ERROR) {
SILC_LOG_DEBUG(("Cannot bind socket"));
+ silc_set_errno_posix(WSAGetLastError());
goto err;
}
rval = connect(sock, &server.sa, SIZEOF_SOCKADDR(server));
if (rval == SOCKET_ERROR) {
SILC_LOG_DEBUG(("Cannot connect UDP stream"));
+ silc_set_errno_posix(WSAGetLastError());
goto err;
}
}
if (len == SOCKET_ERROR) {
err = WSAGetLastError();
+ silc_set_errno_posix(err);
if (err == WSAEWOULDBLOCK) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
SILC_TASK_READ, FALSE);
return -1;
}
- SILC_LOG_DEBUG(("Cannot read from UDP socket: %d", sock->sock));
+ SILC_LOG_DEBUG(("Cannot read from UDP socket: %d: %s", sock->sock,
+ silc_errno_string(silc_errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = err;
return -2;
}
SIZEOF_SOCKADDR(remote));
if (ret == SOCKET_ERROR) {
err = WSAGetLastError();
+ silc_set_errno_posix(err);
if (err == WSAEWOULDBLOCK) {
SILC_LOG_DEBUG(("Could not send immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
SILC_TASK_READ | SILC_TASK_WRITE, FALSE);
return -1;
}
- SILC_LOG_DEBUG(("Cannot send to UDP socket: %s", strerror(errno)));
+ SILC_LOG_DEBUG(("Cannot send to UDP socket: %s",
+ silc_errno_string(silc_errno)));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = err;
return -2;
}
/******************************* TCP Stream *********************************/
typedef struct {
- SilcNetStatus status;
- SilcSocketStreamStatus stream_status;
+ SilcResult status;
SilcStream stream;
SilcFSMStruct fsm;
SilcFSMThreadStruct thread;
SILC_FSM_STATE(silc_net_connect_st_stream);
SILC_FSM_STATE(silc_net_connect_st_finish);
-static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
+static void silc_net_connect_wait_stream(SilcResult status,
SilcStream stream, void *context)
{
SilcNetConnect conn = context;
conn->sop = NULL;
- conn->stream_status = status;
+ conn->status = status;
conn->stream = stream;
SILC_FSM_CALL_CONTINUE(&conn->thread);
}
"host, error %d", conn->remote, WSAGetLastError()));
/** Network unreachable */
- conn->status = SILC_NET_HOST_UNREACHABLE;
+ conn->status = SILC_ERR_UNREACHABLE;
return SILC_FSM_FINISH;
}
}
/** Cannot create socket */
- SILC_LOG_ERROR(("Cannot create socket, error %d", WSAGetLastError()));
+ silc_set_errno_posix(err);
+ SILC_LOG_ERROR(("Cannot create socket, error %d",
+ silc_errno_string(silc_errno)));
return SILC_FSM_FINISH;
}
goto retry;
}
- switch (err) {
- case WSAETIMEDOUT:
- conn->status = SILC_NET_CONNECTION_TIMEOUT;
- break;
- case WSAECONNREFUSED:
- conn->status = SILC_NET_CONNECTION_REFUSED;
- break;
- case WSAEHOSTUNREACH:
- conn->status = SILC_NET_HOST_UNREACHABLE;
- break;
- default:
- break;
- }
+ /* Set error */
+ silc_set_errno_posix(err);
+ conn->status = silc_errno;
- SILC_LOG_ERROR(("Cannot connect to remote host, error %d",
- WSAGetLastError()));
+ SILC_LOG_ERROR(("Cannot connect to remote host: %s",
+ silc_errno_string(silc_errno)));
return SILC_FSM_FINISH;
}
}
if (conn->aborted)
return SILC_FSM_FINISH;
- if (conn->stream_status != SILC_SOCKET_OK) {
+ if (conn->status != SILC_OK) {
/** Stream creation failed */
- if (conn->stream_status == SILC_SOCKET_UNKNOWN_IP)
- conn->status = SILC_NET_UNKNOWN_IP;
- else if (conn->stream_status == SILC_SOCKET_UNKNOWN_HOST)
- conn->status = SILC_NET_UNKNOWN_HOST;
- else
- conn->status = SILC_NET_ERROR;
-
return SILC_FSM_FINISH;
}
/** Stream created successfully */
SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
- conn->status = SILC_NET_OK;
+ conn->status = SILC_OK;
return SILC_FSM_FINISH;
}
{
SilcNetConnect conn;
- if (!remote_ip_addr || remote_port < 1 || !schedule || !callback)
+ if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
SILC_LOG_DEBUG(("Creating connection to host %s port %d",
remote_ip_addr, remote_port));
conn = silc_calloc(1, sizeof(*conn));
if (!conn) {
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
conn->op = silc_async_alloc(silc_net_connect_abort, NULL, conn);
if (!conn->op) {
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
if (local_ip_addr)
- conn->local_ip = strdup(local_ip_addr);
- conn->remote = strdup(remote_ip_addr);
+ conn->local_ip = silc_strdup(local_ip_addr);
+ conn->remote = silc_strdup(remote_ip_addr);
if (!conn->remote) {
silc_async_free(conn->op);
silc_free(conn->local_ip);
silc_free(conn);
- callback(SILC_NET_NO_MEMORY, NULL, context);
+ callback(SILC_ERR_OUT_OF_MEMORY, NULL, context);
return NULL;
}
conn->port = remote_port;
conn->callback = callback;
conn->context = context;
conn->retry = 1;
- conn->status = SILC_NET_ERROR;
+ conn->status = SILC_ERR;
silc_fsm_init(&conn->fsm, conn, silc_net_connect_destructor, NULL, schedule);
silc_fsm_start(&conn->fsm, silc_net_connect_st_thread);
ret[c++] = d;
d = 0;
if (c > 3)
- return FALSE;
+ goto err;
continue;
}
if (!isdigit((int)addr[i - 1]))
- return FALSE;
+ goto err;
d = 10 * d + addr[i - 1] - '0';
if (d > 255)
- return FALSE;
+ goto err;
}
if (c != 3)
- return FALSE;
+ goto err;
ret[c] = d;
- if (bin_len < sizeof(ret))
+ if (bin_len < sizeof(ret)) {
+ silc_set_errno(SILC_ERR_OVERFLOW);
return FALSE;
+ }
memcpy(bin, ret, sizeof(ret));
return TRUE;
+
+ err:
+ return FALSE;
} else {
#ifdef HAVE_IPV6
struct addrinfo hints, *ai;
SilcSockaddr *s;
/* IPv6 address */
- if (bin_len < 16)
+ if (bin_len < 16) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return FALSE;
+ }
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
silc_schedule_get_fd_events(sock->schedule,
sock->sock) |
SILC_TASK_READ, FALSE);
+ silc_set_errno(SILC_ERR_WOULD_BLOCK);
return -1;
}
len = recv(fd, buf, buf_len, 0);
if (len == SOCKET_ERROR) {
len = WSAGetLastError();
+ silc_set_errno_posix(ret);
if (len == WSAEWOULDBLOCK || len == WSAEINTR) {
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot read from socket: %d", sock->sock));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = len;
return -2;
}
ret = send(fd, data, data_len, 0);
if (ret == SOCKET_ERROR) {
ret = WSAGetLastError();
+ silc_set_errno_posix(ret);
if (ret == WSAEWOULDBLOCK) {
SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
silc_schedule_set_listen_fd(sock->schedule, sock->sock,
}
SILC_LOG_DEBUG(("Cannot write to socket"));
silc_schedule_unset_listen_fd(sock->schedule, sock->sock);
- sock->sock_error = ret;
return -2;
}
if (!thread->thread) {
SILC_LOG_ERROR(("Could not create new thread"));
+ silc_set_errno_reason(SILC_ERR, "Could not create new thread");
silc_free(thread);
return NULL;
}
DWORD maxlen = 128;
char username[128];
GetUserName(username, &maxlen);
- return strdup(username);
+ return silc_strdup(username);
}
char *silc_get_real_name(void)
silc_file_write @ 341 ;
silc_file_writefile @ 342 ;
silc_file_writefile_mode @ 343 ;
- silc_check_line @ 344 ;
silc_fingerprint @ 345 ;
silc_format @ 346 ;
silc_get_input @ 347 ;